Typecheckeando tus Lambdas en 10* minutos
Julián Antonielli
@jjant/@_jjant
Un lenguaje muy sencillo
Expresiones
e ::= zero -- Cero
| succ e -- Sucesor
| pred e -- Predecesor
| isZero e
| true
| false
| if e then e else e
data Expr
= Zero
| Succ Expr
| Pred Expr
| IsZero Expr
| Tru
| Fals
| If Expr Expr Expr
deriving (Show, Eq)
> if isZero (succ zero) then true else false
=> false : Boolean
> succ (succ zero)
=> 2 : Natural
Ejemplos
Tipado
Bool
Nat
T ::= Natural
| Boolean
data Type
= Natural
| Boolean
Tipado
Bool
check :: Expr -> Maybe Type
check Tru = Just Boolean
check Fals = Just Boolean
check (If b t e) = do
tyB <- check b
tyT <- check t
tyE <- check e
case (tyB, tyT == tyE) of
(Boolean, True) -> Just tyT
_ -> Nothing
Tipado
Nat
check :: Expr -> Maybe Type
check Zero = Just Natural
check (Succ x) = do
ty <- check x
if ty == Natural
then Just Natural
else Nothing
check (IsZero x) = do
ty <- check x
if ty == Natural
then Just Boolean
else Nothing
check (Pred x) = ...
Demo!
Observación
No hablamos de evaluación, pero no necesitamos evaluar nada durante el typechecking.
Cálculo Lambda Simplemente Tipado
Expresiones
e ::= v -- Variable
| 0, 1, 2.. -- Naturals
| True, False -- Bools
| λ x : T. e -- Lambda
| e1 e2 -- Aplicación
data Expr
= Var Name
| Lit Ground
| App Expr Expr
| Lam Name Type Expr
data Ground
= LInt Int
| LBool Bool
> (\x : Int . x) 23
=> 23
> (\x : Int . \y : Bool . x) 12 True
12
Ejemplos
> False
=> False
Tipado
T ::= Natural
| Boolean
| T1 -> T2
data Type
= TInt
| TBool
| TArr Type Type
Tipado
type Context =
[(Name, Type)]
check :: Expr -> Either TypeError Type
Antes
Ahora
check :: Expr -> Context -> Either TypeError Type
Tipado
check :: Expr -> Context -> Either TypeError Type
check (Var n) ctx = do
case lookup n ctx of
Just ty -> pure ty
Nothing -> Left $ "Variable " <> n <> " not in scope!"
Variables
Tipado
check :: Expr -> Context -> Either TypeError Type
check (Lam ty var body) ctx = do
rangeT <- check body ((var, ty) : ctx)
pure (TArr ty rangeT)
Lambdas
Tipado
check :: Expr -> Context -> Either TypeError Type
check (App term1 term2) ctx = do
ty1 <- check term1 ctx
ty2 <- check term2 ctx
case ty1 of
Func domain range ->
if domain == ty2
then pure range
else Left ("Wrong domain, expected " <> show domain <> " but got " <> show ty2)
_ -> Left ("Expected " <> show term1 <> " to be a function")
Aplicación
Tipado
check :: Expr -> Context -> Either TypeError Type
check (Lit l) _ =
case l of
LInt _ -> TInt
LBool _ -> TBool
Literales
Lo mismo de antes
Y Haskell? Que nos falta?
Hindley-Milner Type System
- (Algo de) Polimorfismo
- ADTs
- Case expressions
- Typeclasses
Recursos
- Type inference from scratch, f(by) 2019: https://www.youtube.com/watch?v=ytPAlhnAKro
- Types and Programming Languages, Benjamin C. Pierce
- Stitch: The Sound Type-Indexed Type Checker: https://www.youtube.com/watch?v=XJ8hm3Tq2k8
- A tutorial implementation of a dependently typed Lambda Calculus: https://www.andres-loeh.de/LambdaPi/LambdaPi.pdf
Evaluación
Small-step semantics
Typechecker
By jjant
Typechecker
- 359