lazy-lambda-calculus: 401e25a58c5b3fb2d37b10c3b32ac9f37a9b3cd9

     1: {-# Language FlexibleInstances          #-}
     2: {-# Language MultiParamTypeClasses      #-}
     3: {-# Language DeriveDataTypeable         #-}
     4: 
     5: module Data.Language.LC where
     6: 
     7: import Control.Monad.Partial
     8: import Data.Nat
     9: import Data.Data
    10: import Data.Typeable
    11: 
    12: -- Lambda calculus terms, with De Bruijn indices and opaque constants
    13: data Term a = Const a
    14:             | Var Nat
    15:             | Lam (Term a)
    16:             | Term a :@ Term a
    17:               deriving (Show, Typeable, Data)
    18: 
    19: -- This lets us abbreviate "Var 0", "Var 1", etc. to "0" "1", etc.
    20: instance Num (Term a) where
    21:   (+)    = error "Cannot add Terms"
    22:   (-)    = error "Cannot subtract Terms"
    23:   (*)    = error "Cannot multiply Terms"
    24:   abs    = error "Cannot abs a Term"
    25:   negate = error "Cannot negate a Term"
    26:   signum = error "Cannot signum a Term"
    27:   fromInteger = Var . fromInteger
    28: 
    29: instance Eq a => Eq (Term a) where
    30:   (Const x)  == (Const y)  = x == y
    31:   (Var   x)  == (Var   y)  = x == y
    32:   (Lam   x)  == (Lam   y)  = x == y
    33:   (l1 :@ r1) == (l2 :@ r2) = l1 == l2 && r1 == r2
    34: 
    35: -- The results of evaluation: either a value or a closure
    36: data Val a = C a
    37:            | F (Partial (Val a) -> Partial (Val a))
    38: 
    39: instance Show a => Show (Val a) where
    40:   show (C x) = "(C " ++ show x ++ ")"
    41:   show (F f) = "(F <function>)"
    42: 
    43: instance Eq a => Eq (Val a) where
    44:   (C x) == (C y) = x == y
    45:   (F x) == (F y) = error "Cannot compare function Vals"
    46:   _     == _     = False
    47: 
    48: instance Functor Val where
    49:   fmap f (C x) = C (f x)
    50:   fmap f (F g) = error "Cannot map embedded function"
    51: 
    52: valMap :: (a -> b) -> Val a -> Val b
    53: valMap f (C x) = C (f x)
    54: valMap f (F g) = error "Cannot map over function"
    55: 
    56: valLift :: (a -> a) -> Val a
    57: valLift f = F (fmap (fmap f))
    58: 
    59: liftVal :: Val a -> Val (Either b a)
    60: liftVal (C x) = C (Right x)
    61: liftVal (F f) = F (fmap liftVal . f . fmap lowerVal)
    62: 
    63: lowerVal :: Val (Either a b) -> Val b
    64: lowerVal (C (Right x)) = C x
    65: lowerVal (F f) = F (fmap lowerVal . f . fmap liftVal)
    66: 
    67: flipVal :: Val (Either a b) -> Val (Either b a)
    68: flipVal (C (Left  x)) = C (Right x)
    69: flipVal (C (Right x)) = C (Left  x)
    70: flipVal (F f)         = F (fmap flipVal . f . fmap flipVal)
    71: 
    72: -- Apply a function Val to an argument
    73: ($$) (F f) x = f (Now (C x))
    74: ($$) (C f) x = error "Cannot apply C as a function"
    75: 
    76: -- Evaluation environment
    77: type Env a = [Partial (Val a)]
    78: 
    79: -- Fully evaluates a Term, using Partial to handle nontermination
    80: eval' :: Term a -> Env a -> Partial (Val a)
    81: eval' (Const c) env = Now (C c)
    82: eval' (Var   n) env = let Just x = lookUp env n in x
    83: eval' (Lam   f) env = Now (F (\a -> eval' f (a:env)))
    84: eval' (f :@  x) env = do F f' <- eval' f env
    85:                          Later (f' (eval' x env))
    86: 
    87: -- Entry point for eval'
    88: eval t | closed t = eval' t []
    89: eval t            = error "Can only evaluate closed Terms"
    90: 
    91: -- Abbreviation for performing N steps
    92: evalN n = force n . eval
    93: 
    94: -- Predicate for capping the number of free variables in a Term
    95: freeVars :: Nat -> Term a -> Bool
    96: freeVars n (Const _) = True
    97: freeVars n (Var   m) = m < n
    98: freeVars n (Lam   f) = freeVars (S n) f
    99: freeVars n (l :@ r)  = freeVars n l && freeVars n r
   100: 
   101: -- Predicate for ensuring a Term has no free variables
   102: closed :: Term a -> Bool
   103: closed = freeVars 0
   104: 
   105: castTerm :: Term a -> Term b
   106: castTerm (Const x) = error "Cannot cast Constants"
   107: castTerm (Var   n) = Var n
   108: castTerm (Lam   f) = Lam (castTerm f)
   109: castTerm (l :@  r) = castTerm l :@ castTerm r
   110: 
   111: -- Infinite loop
   112: omega = Lam (0 :@ 0) :@ Lam (0 :@ 0)
   113: 
   114: -- Y combinator
   115: yComb = Lam (Lam (1 :@ (0 :@ 0)) :@ Lam (1 :@ (0 :@ 0)))
   116: 
   117: -- Z combinator
   118: zComb = Lam (Lam (1 :@ Lam (1 :@ 1 :@ 0)) :@ Lam (1 :@ Lam (1 :@ 1 :@ 0)))

Generated by git2html.