packages feed

LambdaINet-0.2.0.0: src/Lambda.lhs

Generalized Lambda for Lambdascope

> {-# LANGUAGE DoRec #-}

> module Lambda (
>   Term(..),
>   termToNet,
>   termToNode,
>   netToTerm,
>   meta,
>   pretty
>   ) where

> -- import Diagram hiding (S)
> import INet

> import Control.Monad.Fix
> import Data.IntMap hiding (map)
> import Prelude hiding (take, drop, head, tail, cycle)

> data Term = Z | S Term | Abs Term | App Term Term 
>           | Y Term                                -- fix point
>           | Tup Term Term | Fst Term | Snd Term   -- tuple
>           | VInt Int | VStr String                -- value
>           | VFunc Int String Term                 -- function
>   deriving (Eq, Show)

We need less strict list operators in order for the recursive do to work.

> head ~(x:xs) = x
> tail ~(x:xs) = xs

> take 0 x = []
> take i x = head x : take (i - 1) (tail x)
> drop 0 x = x
> drop i x = drop (i - 1) (tail x)

> erasers [] = return []
> erasers (x:xs) = do
>   rec e <- eraser x
>       es <- erasers xs
>   return $ e : es

> termToNet i Z ps = do
>   let inp = head ps
>       out = head (drop i ps)
>       mid = take (i - 1) (tail ps)
>   a <- dummy inp out     -- dummy used here for proper self-loop
>   es <- erasers mid
>   return $ (a : es) ++ [a]

> termToNet i x@(S t) ps = do
>   let inp = head ps
>       out = head (drop i ps)
>       mid = take (i - 1) (tail ps)
>   rec d <- delimiter (head n) inp 0
>       n <- termToNet (i - 1) t (d : mid)
>       e <- eraser out
>   return $ (d : tail n) ++ [e]

> termToNet i x@(Abs t) ps = do
>   let inp = head ps
>   rec a <- abstractor inp (head n) (head (drop (i + 1) n))
>       n <- termToNet (i + 1) t ((a : tail ps) ++ [a])
>   let mid = take i (tail n)
>   return $ a : mid

> termToNet i x@(App t1 t2) ps = do
>   let inp = head ps
>   rec a <- applicator (head m) (head n) inp
>       m <- termToNet i t1 (a : qs)
>       n <- termToNet i t2 (a : qs)
>       qs <- dup i (tail m) (tail n) (tail ps)
>   return $ a : qs
>   where 
>     dup 0 _ _ _ = return []
>     dup i ~(a:as) ~(b:bs) ~(c:cs) = do
>       d <- duplicator c b a 0
>       ds <- dup (i - 1) as bs cs
>       return $ d : ds

> {-
> termToNet i x@(Y t) ps = do
>   let inp = head ps
>   rec a <- bigY (head n) inp 0
>       n <- termToNet i t (a : tail ps)
>   return $ a : tail n
> -}

> termToNet i x@(Y t) ps = do
>   let inp = head ps
>   rec d <- cycle a b inp 0
>       b <- dummy a d
>       a <- applicator (head m) b d
>       m <- termToNet i t (a : tail ps)
>   return $ d : tail m

> termToNet i x@(Tup t1 t2) ps = do
>   let inp = head ps
>   rec a <- tuple inp (head m) (head n) 
>       m <- termToNet i t1 (a : qs)
>       n <- termToNet i t2 (a : qs)
>       qs <- dup i (tail m) (tail n) (tail ps)
>   return $ a : qs
>   where 
>     dup 0 _ _ _ = return []
>     dup i ~(a:as) ~(b:bs) ~(c:cs) = do
>       d <- duplicator c b a 0
>       ds <- dup (i - 1) as bs cs
>       return $ d : ds

> termToNet i x (inp:out) = 
>   case x of 
>     Fst t -> do
>       rec a <- twopin 1 "fst" (head n) inp
>           n <- termToNet i t (a:out)
>       return $ a : tail n
>     Snd t -> do
>       rec a <- twopin 1 "snd" (head n) inp
>           n <- termToNet i t (a:out)
>       return $ a : tail n
>     VInt i -> do
>       rec a <- single (show i) inp
>           n <- erasers out
>       return $ a : n
>     VStr s -> do
>       rec a <- single s inp
>           n <- erasers out
>       return $ a : n
>     VFunc arity l t -> do
>       rec a <- twopin arity l (head n) inp
>           n <- termToNet i t (a:out)
>       return $ a : tail n

> termToNode t = do
>   rec e <- initiator a 
>       [a] <- termToNet 0 t [e]
>   return e

> netToTerm :: INet -> Term
> netToTerm (net, _) = 
>   let Just (i, (_, [(b, u)], _)) = findInitiator (toList net)
>   in toTerm (net ! b)
>   where
>     toTerm (Abstractor, [_, (b, _), _], _) = Abs (toTerm (net ! b))
>     toTerm (Applicator', [_, (b, _), (c, _)], _) = App (toTerm (net ! b)) (toTerm (net ! c))
>     toTerm (Delimiter', [_, (b, _)], _) = S (toTerm (net ! b))
>     toTerm (Eraser, _, _) = Z
>     toTerm (Constructor l, xs, _) = 
>       case l of 
>         "T" -> Tup (toTerm (net ! fst (xs !! 1))) (toTerm (net ! fst (xs !! 2)))
>     toTerm (TwoPin' arity l, p, _) = 
>       case l of
>         "fst" -> Fst (toTerm (net ! fst (p !! 1))) 
>         "snd" -> Snd (toTerm (net ! fst (p !! 1))) 
>         l -> VFunc arity l (toTerm (net ! fst (p !! 1)))
>     toTerm (Single' l, p, _) =
>       case l of
>         (a:as) -> if a >= '0' && a <= '9' 
>           then VInt (read l)
>           else VStr l 
>     toTerm n = error $ "illegal toTerm input: " ++ show n

meta rules for tuple handling, etc.

> meta (i, (TwoPin arity l, [_, (c, u)], _)) (j, (bt, bp, _)) = 
>   case (l, bt) of
>     ("fst", Constructor "T") -> Just . project 1
>     ("snd", Constructor "T") -> Just . project 2
>     (_, Single m) -> Just . applyFunc m
>     _ -> const Nothing
>   where
>     project n (net, maxID) =
>       let (d, v) = bp !! n
>           (e, w) = bp !! (3 - n)
>           f = maxID + 1
>           f_ = (Eraser, [(e, w)], Nothing)
>       in ((adjust (\ (ct, cp, cv) -> (ct, replace u (d, v) cp, cv)) c .
>         adjust (\ (dt, dp, dv) -> (dt, replace v (c, u) dp, dv)) d .
>         adjust (\ (et, ep, ev) -> (et, replace w (f, 0) ep, ev)) e .
>         insert f f_ . delete i . delete j) net, maxID + 1)
>     applyFunc m (net, maxID) =
>       let l' = "(" ++ l ++ " " ++ m ++ ")"
>           f = maxID + 1
>           f_ = (Abstractor, [(c, u), (i, 1), (i, 0)], Nothing)
>       in if arity == 1 
>         then ((adjust (\ (at, ap, av) -> (Single l', [(c, u)], av)) i .
>           adjust (\ (ct, cp, cv) -> (ct, replace u (i, 0) cp, cv)) c .
>           delete j) net, maxID + 1)
>         else ((adjust (\ (at, ap, av) -> (TwoPin (arity - 1) l', [(f, 2), (f, 1)], av)) i .
>           adjust (\ (ct, cp, cv) -> (ct, replace u (f, 0) cp, cv)) c .
>           insert f f_ . delete j) net, maxID + 1)

> meta a b@(_, (TwoPin _ _, _, _)) = meta b a 
> meta _ _ = const Nothing

a pretty printer for generalized lambda terms.

> show' (x:xs) vars Z = x
> show' (x:xs) vars (S t) = show' xs vars t
> show' env (v:vs) (Abs t) = "(\\" ++ v ++ "." ++ show' (v:env) vs t ++ ")"
> show' env vars (App t t') = "(" ++ show' env vars t ++ " " ++ show' env vars t' ++ ")"
> show' env vars (Y t) = "Y(\\" ++ show' env vars t ++ ")"
> show' env vars (Tup t t') = "(" ++ show' env vars t ++ ", " ++ show' env vars t' ++ ")"
> show' env vars (Fst t) = "(fst " ++ show' env vars t ++ ")"
> show' env vars (Snd t) = "(snd " ++ show' env vars t ++ ")"
> show' env vars (VInt i) = show i
> show' env vars (VStr s) = show s
> show' env vars (VFunc i s t) = s ++ "(" ++ show' env vars t ++ ")"

> pretty = show' [] freshVars

Fresh variables

> freshVars = atoz ++ map (\[x,y]->y++x) (sequence [nats, atoz])
>  where
>    atoz = map (\x -> ['_', x]) ['a' .. 'z']
>    nats = map show [0..]