lambda for HM
authorTomáš Musil <tomik.musil@gmail.com>
Fri, 4 Sep 2015 00:25:06 +0000 (02:25 +0200)
committerTomáš Musil <tomik.musil@gmail.com>
Fri, 4 Sep 2015 00:25:06 +0000 (02:25 +0200)
src/HM/Lambda.hs

index e85041c..1d76e1f 100644 (file)
+{-# LANGUAGE PatternSynonyms #-}
+
 module HM.Lambda where
 
 import Control.Monad.State
 import Data.Map as M
 
-import HM.Term
+import qualified HM.Term as HMT
+
+type VarName = String
+
+data LTerm = Var VarName | Lam VarName LTerm | Let VarName LTerm LTerm | App LTerm LTerm deriving (Eq, Show)
+
+pattern RedEx x t s = App (Lam x t) s
+
+convert :: HMT.TypedTerm -> LTerm
+convert (HMT.TTerm t _) = convert (HMT.NTTerm t)
+convert (HMT.NTTerm (HMT.Var x)) = Var x
+convert (HMT.NTTerm (HMT.Lam x t)) = Lam x $ convert t
+convert (HMT.NTTerm (HMT.Let x y z)) = Let x (convert y) (convert z)
+convert (HMT.NTTerm (HMT.App y z)) = App (convert y) (convert z)
+
+isFreeIn :: VarName -> LTerm -> Bool
+isFreeIn x (Var v) = x == v
+isFreeIn x (App t u) = x `isFreeIn` t || x `isFreeIn` u
+isFreeIn x (Lam v t) = x /= v && x `isFreeIn` t
+isFreeIn x (Let v t u) = x `isFreeIn` t || x /= v && x `isFreeIn` u
+
+rename :: LTerm -> LTerm
+rename (Lam x t) = Lam n (substitute x (Var n) t)
+  where n = rnm x 
+        rnm v = if (v ++ "r") `isFreeIn` t then rnm (v ++ "r") else v ++ "r"
+rename _ = error "TODO vymyslet reprezentaci, kde pujde udelat fce, ktera bere jen Lambdy"
+
+substitute :: VarName -> LTerm -> LTerm -> LTerm
+substitute a b (Var x) = if x == a then b else Var x
+substitute a b (Lam x t) 
+  | x == a = Lam x t
+  | x `isFreeIn` b = substitute a b $ rename (Lam x t)
+  | otherwise = Lam x (substitute a b t)
+substitute a b (Let x t u) = error "TODO implement let"
+substitute a b (App t u) = App (substitute a b t) (substitute a b u)
+
+reduce :: LTerm -> LTerm
+reduce (Var x) = Var x
+reduce (Lam x t) = Lam x (reduce t)
+reduce (App t u) = app (reduce t) u
+  where app (Lam x v) w = reduce $ substitute x w v
+        app a b = App a (reduce b)
+
+data Strategy = Eager | Lazy
+
+reduceStep :: LTerm -> LTerm
+reduceStep (RedEx x s t) = substitute x t s
+reduceStep t = t
+
+data Z = R LTerm Z | L Z LTerm | ZL VarName Z | E
+data D = Up | Down
+type TermZipper = (LTerm, Z, D)
+
+move :: TermZipper -> TermZipper
+move (App l r, c, Down) = (l, L c r, Down)
+move (Lam x t, c, Down) = (t, ZL x c, Down)
+move (Var x, c, Down) = (Var x, c, Up)
+move (t, L c r, Up) = (r, R t c, Down)
+move (t, R l c, Up) = (App l t, c, Up)
+move (t, ZL x c, Up) = (Lam x t, c, Up)
+move (t, E, Up) = (t, E, Up)
+
+unmove :: TermZipper -> TermZipper
+unmove (t, L c r, Down) = (App t r, c, Down)
+unmove x = x
+
+-- getTerm :: TermZipper -> Term
+
+travPost :: (Monad m) => (LTerm -> m LTerm) -> LTerm -> m LTerm
+travPost fnc term = tr fnc (term, E, Down)
+  where 
+    tr f (t@RedEx{}, c, Up) = do
+      nt <- f t
+      tr f (nt, c, Down)
+    tr _ (t, E, Up) = return t
+    tr f (t, c, Up) = tr f $ move (t, c, Up)
+    tr f (t, c, Down) = tr f $ move (t, c, Down)
+
+travPre :: (Monad m) => (LTerm -> m LTerm) -> LTerm -> m LTerm
+travPre fnc term = tr fnc (term, E, Down)
+  where 
+    tr f (t@RedEx{}, c, Down) = do
+      nt <- f t
+      tr f $ unmove (nt, c, Down)
+    tr _ (t, E, Up) = return t
+    tr f (t, c, Up) = tr f $ move (t, c, Up)
+    tr f (t, c, Down) = tr f $ move (t, c, Down)
+
+-- |
+--
+-- >>> toNormalForm Eager 100 cI
+-- Just (λx.x)
+--
+-- >>> toNormalForm Eager 100 $ App cI cI
+-- Just (λx.x)
+--
+-- >>> toNormalForm Eager 100 $ (App (App cK cI) cY)
+-- Nothing
+--
+-- >>> toNormalForm Lazy 100 $ (App (App cK cI) cY)
+-- Just (λx.x)
+--
+-- prop> within 10000000 $ (\ t u -> t == u || t == Nothing || u == Nothing) (alphaNorm <$> toNormalForm Lazy 100 x) (alphaNorm <$> toNormalForm Eager 100 x)
 
-type Env = M.Map VarName Term
-type LI a = State Env a
+-- inf = tRead "(\\d.a ((\\d c.c d c) (\\x y z.x z (y z)) (\\f.(\\x.f (x x)) (\\x.f (x x))) e))"
 
-stripType :: TypedTerm -> Term
-stripType (NTTerm t) = t
-stripType (TTerm t _) = t
+toNormalForm :: Strategy -> Int -> LTerm -> Maybe LTerm
+toNormalForm Eager n = flip evalStateT 0 . travPost (cnt >=> short n >=> return . reduceStep)
+toNormalForm Lazy  n = flip evalStateT 0 . travPre  (cnt >=> short n >=> return . reduceStep)
 
+cnt :: (Monad m) => LTerm -> StateT Int m LTerm
+cnt t@RedEx{} = do
+  modify (+ 1)
+  return t
+cnt t = return t
 
+short :: Int -> LTerm -> StateT Int Maybe LTerm
+short maxN t = do
+  n <- get
+  if n > maxN
+    then lift Nothing
+    else return t