home *** CD-ROM | disk | FTP | other *** search
- --
- -- 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")
-
- -------------------------------------------------------------------------------
-