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: | Line 8: | ||
=={{header|AppleScript}}== |
=={{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 |
|||
{{trans|JavaScript}} |
|||
-- 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 |
|||
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. |
|||
-- a -> [a] |
|||
on unit(a) |
|||
[a] |
|||
end unit |
|||
-- TEST ------------------------------------------------------------------------ |
|||
<lang AppleScript>on run |
|||
on run |
|||
-- Pythagorean triples drawn from integers in the range [1..n] |
-- 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)} |
-- {(x, y, z) | x <- [1..n], y <- [x+1..n], z <- [y+1..n], (x^2 + y^2 = z^2)} |
||
Line 21: | Line 42: | ||
pythagoreanTriples(25) |
pythagoreanTriples(25) |
||
--> {{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, |
--> {{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 |
end run |
||
Line 28: | Line 50: | ||
on pythagoreanTriples(maxInteger) |
on pythagoreanTriples(maxInteger) |
||
script X |
script X |
||
on |
on |λ|(X) |
||
script Y |
script Y |
||
on |
on |λ|(Y) |
||
script Z |
script Z |
||
on |
on |λ|(Z) |
||
if X * X + Y * Y = Z * Z then |
if X * X + Y * Y = Z * Z then |
||
unit([X, Y, Z]) |
unit([X, Y, Z]) |
||
Line 38: | Line 60: | ||
[] |
[] |
||
end if |
end if |
||
end |
end |λ| |
||
end script |
end script |
||
bind(Z, |
bind(Z, enumFromTo(1 + Y, maxInteger)) |
||
end |
end |λ| |
||
end script |
end script |
||
bind(Y, |
bind(Y, enumFromTo(1 + X, maxInteger)) |
||
end |
end |λ| |
||
end script |
end script |
||
bind(X, |
bind(X, enumFromTo(1, maxInteger)) |
||
end pythagoreanTriples |
end pythagoreanTriples |
||
-- GENERIC FUNCTIONS --------------------------------------------------------- |
|||
-- MONADIC FUNCTIONS (for list monad) |
|||
-- enumFromTo :: Int -> Int -> [Int] |
|||
-- Monadic bind for lists is simply ConcatMap |
|||
on enumFromTo(m, n) |
|||
-- 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 lambda(a, b) |
|||
a & b |
|||
end lambda |
|||
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 |
|||
-- GENERIC LIBRARY FUNCTIONS |
|||
-- map :: (a -> b) -> [a] -> [b] |
|||
on map(f, xs) |
|||
set mf to mReturn(f) |
|||
set lng to length of xs |
|||
set lst to {} |
|||
repeat with i from 1 to lng |
|||
set end of lst to mf's lambda(item i of xs, i, xs) |
|||
end repeat |
|||
return lst |
|||
end map |
|||
-- foldl :: (a -> b -> a) -> a -> [b] -> a |
|||
on foldl(f, startValue, xs) |
|||
set mf to mReturn(f) |
|||
set v to startValue |
|||
set lng to length of xs |
|||
repeat with i from 1 to lng |
|||
set v to mf's lambda(v, item i of xs, i, xs) |
|||
end repeat |
|||
return v |
|||
end foldl |
|||
-- range :: Int -> Int -> [Int] |
|||
on range(m, n) |
|||
if n < m then |
if n < m then |
||
set d to -1 |
set d to -1 |
||
Line 117: | Line 90: | ||
end repeat |
end repeat |
||
return lst |
return lst |
||
end |
end enumFromTo |
||
-- foldl :: (a -> b -> a) -> a -> [b] -> a |
|||
-- Script | Handler -> Script |
|||
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) |
on mReturn(f) |
||
if class of f is script then |
if class of f is script then |
||
Line 125: | Line 123: | ||
else |
else |
||
script |
script |
||
property |
property |λ| : f |
||
end script |
end script |
||
end if |
end if |
||
end mReturn |
end mReturn</lang> |
||
</lang> |
|||
{{Out}} |
{{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> |
<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> |
||