Simply typed lambda calculus with failure, in Haskell

后端 未结 2 763
生来不讨喜
生来不讨喜 2021-01-18 12:43

I\'m a newcomer to Haskell, so apologies if this question doesn\'t make too much sense.

I want to be able to implement simply typed lambda expressions in Haskell in

2条回答
  •  渐次进展
    2021-01-18 13:21

    Pretty standard stuff. Just write a type-checker, and only evaluate the term when it typechecks. evalMay does this. You can of course enrich the set of constants and base types; I just used one of each for simplicity.

    import Control.Applicative ((<$), (<$>))
    import Control.Monad (guard)
    import Safe (atMay)
    
    data Type
        = Base
        | Arrow Type Type
        deriving (Eq, Ord, Read, Show)
    
    data Term
        = Const
        | Var Int -- deBruijn indexing; the nearest enclosing lambda binds Var 0
        | Lam Type Term
        | App Term Term
        deriving (Eq, Ord, Read, Show)
    
    check :: [Type] -> Term -> Maybe Type
    check env Const = return Base
    check env (Var v) = atMay env v
    check env (Lam ty tm) = Arrow ty <$> check (ty:env) tm
    check env (App tm tm') = do
        Arrow i o <- check env tm
        i' <- check env tm'
        guard (i == i')
        return o
    
    eval :: Term -> Term
    eval (App tm tm') = case eval tm of
        Lam _ body -> eval (subst 0 tm' body)
    eval v = v
    
    subst :: Int -> Term -> Term -> Term
    subst n tm Const = Const
    subst n tm (Var m) = case compare m n of
        LT -> Var m
        EQ -> tm
        GT -> Var (m-1)
    subst n tm (Lam ty body) = Lam ty (subst (n+1) tm body)
    subst n tm (App tm' tm'') = App (subst n tm tm') (subst n tm tm'')
    
    evalMay :: Term -> Maybe Term
    evalMay tm = eval tm <$ check [] tm
    

提交回复
热议问题