home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
gofer230.zip
/
Progs
/
Gofer
/
Demos
/
Lamvar
/
lvexamples
< prev
next >
Wrap
Text File
|
1994-06-23
|
7KB
|
245 lines
--
-- Examples for use with LambdaVr
--
-- Simple functional version: -------------------------------------------------
data Tree a = Leaf a | Tree a :^: Tree a
label :: Tree a -> Tree (a,Int)
label tree = fst (lab tree 0)
where lab (Leaf n) c = (Leaf (n,c), c+1)
lab (l :^: r) c = (l' :^: r', c'')
where (l',c') = lab l c
(r',c'') = lab r c'
-- Lambda var version: --------------------------------------------------------
counter = var (\cnt -> 0 =: cnt >>
result (cnt ? \c ->
c+1 =: cnt >>
result c))
label0 tree = pure (counter >>= lab tree)
lab (Leaf n) ctr = ctr >>= \c ->
result (Leaf (n,c))
lab (l :^: r) ctr = lab l ctr >>= \l' ->
lab r ctr >>= \r' ->
result (l' :^: r')
{- Here is an example where pure is not safe:
label0 tree = pure (lab tree)
where ctr = pure counter
lab (Leaf n) = ctr >>= \c ->
result (Leaf (n,c))
lab (l :^: r) = lab l >>= \l' ->
lab r >>= \r' ->
result (l' :^: r')
gives label0 aTree = (Leaf (1,0) :^: Leaf (2,1)) :^:
(Leaf (3,2) :^: Leaf (4,3))
whereas:
label0 tree = pure (lab tree)
where lab (Leaf n) = pure counter >>= \c ->
result (Leaf (n,c))
lab (l :^: r) = lab l >>= \l' ->
lab r >>= \r' ->
result (l' :^: r')
gives label0 aTree = (Leaf (1,0) :^: Leaf (2,0)) :^:
(Leaf (3,0) :^: Leaf (4,0))
-}
-- State monad version: -------------------------------------------------------
data State s a = ST (s -> (a,s))
instance Functor (State s) where
map f (ST st) = ST (\s -> let (x,s') = st s in (f x, s'))
instance Monad (State s) where
result x = ST (\s -> (x,s))
ST m `bind` f = ST (\s -> let (x,s') = m s
ST f' = f x
in f' s')
startingWith :: State s a -> s -> a
ST m `startingWith` v = fst (m v)
incr :: State Int Int
incr = ST (\s -> (s,s+1))
label1 :: Tree a -> Tree (a,Int)
label1 tree = lab tree `startingWith` 0
where lab (Leaf n) = incr `bind` \c ->
result (Leaf (n,c))
lab (l :^: r) = lab l `bind` \l' ->
lab r `bind` \r' ->
result (l' :^: r')
label2 :: Tree a -> Tree (a,Int)
label2 tree = lab tree `startingWith` 0
where lab (Leaf n) = [ Leaf (n,c) | c <- incr ]
lab (l :^: r) = [ l :^: r | l <- lab l, r <- lab r ]
-- sample data: ---------------------------------------------------------------
aTree = balance [1..4]
balance ns | len == 1 = Leaf (head ns)
| otherwise = balance (take h ns) :^: balance (drop h ns)
where len = length ns
h = len `div` 2
balance' ns = bal (length ns) ns
where bal l ns | l == 1 = Leaf (head ns)
| otherwise = let h = l `div` 2
in bal h (take h ns) :^: bal (l-h) (drop h ns)
-------------------------------------------------------------------------------
-- A swap function:
swap :: Var a -> Var a -> Proc ()
swap v w = v ? \x ->
w ? \y ->
x =: w >>
y =: v
valOf v = v ? result
-- usage: swap elements of arrays a and b in the range between 1 and n
--
--seq [swap (a!i) (b!i) | i <- [1..n]]
increment v = v ? \val -> val+1 =: v
anotherTest = var (\v -> 0 =: v >>
increment v >>
increment v >>
increment v >>
increment v >>
v ?
result)
swapTest = var (\v ->
var (\w ->
"I'm v" =: v >>
"I'm w" =: w >>
swap v w >>
v ? \vValue ->
w ? \wValue ->
result (vValue,wValue)))
swapTest2 = var (\v ->
var (\w ->
0 =: v >>
10 =: w >>
v ? \vValue ->
vValue+1 =: v >>
swap v w >>
v ? \vValue ->
w ? \wValue ->
result (vValue,wValue)))
-- A queue implementation
-- First, its interface:
type Queue a = ( a -> Proc (), -- put
Proc a, -- get
Proc Bool -- isempty
)
-- Procedures to take apart the method tuple:
put (p, g, i) = p
get (p, g, i) = g
isempty (p, g, i) = i
-- Now, the implementation in terms of a linked list:
data Link a = Link a (Var (Link a))
mkqueue :: Proc (Queue Int)
mkqueue =
var (\v ->
var (\front -> v =: front >>
var (\rear -> v =: rear >>
result
( \x -> -- put x
rear ? \r ->
var (\r' ->
Link x r' =: r >>
r' =: rear)
,
front ? \f -> -- get
f ? \ (Link x f') ->
f' =: front >>
result x
,
front ? \f -> -- isempty
rear ? \r ->
result (f == r)
)
)))
-- Usage:
qTest = pure (mkqueue >>= \q ->
put q 1 >>
get q >>= \first ->
isempty q >>= \empty ->
result (if first == 1 && empty then "so should it be"
else "something's wrong"))
-- An alternative way to write the same thing:
mkqueue1 :: Proc (Queue Int)
mkqueue1 =
newvar >>= \v ->
newvar >>= \front ->
v =: front >>
newvar >>= \rear ->
v =: rear >>
let
put x = rear? \r ->
newvar >>= \r' ->
Link x r' =: r >>
r' =: rear
get = front? \f ->
f? \(Link x f') ->
f' =: front >>
result x
isempty = front ? \f ->
rear ? \r ->
result (f==r)
in
result (put, get, isempty)
-- Usage:
qTest1 = pure (mkqueue1 >>= \q ->
put q 1 >>
get q >>= \first ->
isempty q >>= \empty ->
result (if first == 1 && empty then "so should it be"
else "something's wrong"))
qTest2 = mkqueue1 >>= \q ->
put q 1 >>
get q >>= \first ->
isempty q >>= \empty ->
result (if first == 1 && empty then "so should it be"
else "something's wrong")
-------------------------------------------------------------------------------