Monads/List monad: Difference between revisions
Content added Content deleted
(→{{header|AppleScript}}: Renamed 2 script objects for better ratio of signal-to-noise) |
(→{{header|AppleScript}}: Updated primitives) |
||
Line 8:
=={{header|AppleScript}}==
{{trans|JavaScript}}
We can use a list monad in AppleScript to express set comprehension for the Pythagorean triples, but the lack of nestable first class (and anonymous) functions means that the closure can only be achieved using script objects, which makes the idiom rather less direct and transparent. AppleScript is creaking at the seams here.
<lang AppleScript>-- MONADIC FUNCTIONS (for list monad) ------------------------------------------
-- Monadic bind for lists is simply ConcatMap
-- which applies a function f directly to each value in the list,
-- and returns the set of results as a concat-flattened list
-- bind :: (a -> [b]) -> [a] -> [b]
on bind(f, xs)
-- concat :: a -> a -> [a]
script concat
on |λ|(a, b)
a & b
end |λ|
end script
foldl(concat, {}, map(f, xs))
end bind
-- Monadic return/unit/inject for lists: just wraps a value in a list
-- a -> [a]
on unit(a)
[a]
end unit
-- TEST ------------------------------------------------------------------------
on run
-- Pythagorean triples drawn from integers in the range [1..n]
-- {(x, y, z) | x <- [1..n], y <- [x+1..n], z <- [y+1..n], (x^2 + y^2 = z^2)}
Line 21 ⟶ 42:
pythagoreanTriples(25)
--> {{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17},
-- {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}
end run
Line 28 ⟶ 50:
on pythagoreanTriples(maxInteger)
script X
on
script Y
on
script Z
on
if X * X + Y * Y = Z * Z then
unit([X, Y, Z])
Line 38 ⟶ 60:
[]
end if
end
end script
bind(Z,
end
end script
bind(Y,
end
end script
bind(X,
end pythagoreanTriples
-- GENERIC FUNCTIONS ---------------------------------------------------------
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if n < m then
set d to -1
Line 117 ⟶ 90:
end repeat
return lst
end
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
Line 125 ⟶ 123:
else
script
property
end script
end if
end mReturn</lang>
{{Out}}
<lang AppleScript>{{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}</lang>
|