Jump to content

Monads/List monad: Difference between revisions

→‎{{header|AppleScript}}: Updated primitives
(→‎{{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
{{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]
-- {(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}}
-- {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}
end run
Line 28 ⟶ 50:
on pythagoreanTriples(maxInteger)
script X
on lambda|λ|(X)
script Y
on lambda|λ|(Y)
script Z
on lambda|λ|(Z)
if X * X + Y * Y = Z * Z then
unit([X, Y, Z])
Line 38 ⟶ 60:
[]
end if
end lambda|λ|
end script
bind(Z, rangeenumFromTo(1 + Y, maxInteger))
end lambda|λ|
end script
bind(Y, rangeenumFromTo(1 + X, maxInteger))
end lambda|λ|
end script
bind(X, rangeenumFromTo(1, maxInteger))
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
set d to -1
Line 117 ⟶ 90:
end repeat
return lst
end rangeenumFromTo
 
-- 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)
if class of f is script then
Line 125 ⟶ 123:
else
script
property lambda|λ| : f
end script
end if
end mReturn</lang>
</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>
 
9,655

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.