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}, {9, 12, 15}, {12, 16, 20}, {15, 20, 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
end run
Line 28: Line 50:
on pythagoreanTriples(maxInteger)
on pythagoreanTriples(maxInteger)
script X
script X
on lambda(X)
on |λ|(X)
script Y
script Y
on lambda(Y)
on |λ|(Y)
script Z
script Z
on lambda(Z)
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 lambda
end |λ|
end script
end script
bind(Z, range(1 + Y, maxInteger))
bind(Z, enumFromTo(1 + Y, maxInteger))
end lambda
end |λ|
end script
end script
bind(Y, range(1 + X, maxInteger))
bind(Y, enumFromTo(1 + X, maxInteger))
end lambda
end |λ|
end script
end script
bind(X, range(1, maxInteger))
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 range
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 lambda : f
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>