Skip to content

Latest commit

 

History

History
152 lines (110 loc) · 3 KB

lab07types.md

File metadata and controls

152 lines (110 loc) · 3 KB

Napisz kontrolę typów dla rachunku lambda z prostymi typami. Mozliwe rozszerzenia: let, unifikacja, rekonstrukcja typów,

Jako skladni abstrakcyjnej można uzyć na przykład

module IntLambda where

infixr 5 :->
data Type = TInt | Type :-> Type 
  deriving Eq

type Name = String
data Exp = EInt Int | EVar Name 
     | ELam Name Type Exp | EApp Exp Exp

-- Przykładowe lambda-termy
type Exp1 = Type -> Exp
type Exp2 = Type -> Exp1
type Exp3 = Type -> Exp2

int :: Type
int = TInt

mkI :: Exp1
mkI a = ELam "x" a $ EVar "x"

mkK :: Exp2
mkK a b = ELam "x" a $ ELam "y" b $ EVar "x"

intK = mkK int int

mkS :: Exp3
mkS a b c = ELam "x" a $ ELam "y" b $ ELam "z" c
      $ EApp 
	 (EApp (EVar "x") (EVar "z")) 
	 (EApp (EVar "y") (EVar "z")) 

intS = mkS (int:->int:->int) (int:->int) int

-- kombinator omega nie typuje sie w prostym rachunku lambda
mkOmega :: Exp1
mkOmega t = ELam "x" t $ EApp (EVar "x") (EVar "x")

intOmega = mkOmega TInt

W pierwszej wersji mozna użyć po prostu error do raportowania błedów, potem jednak lepiej zrobić lepsze raportowanie, np z ErrorT

Przykładowa sesja:

    *Main> typeOf (EInt 42)
    Right int

    *Main> typeCheck intK
    int -> int -> int

    *Main> typeCheck intS
    (int -> int -> int) -> (int -> int) -> int -> int

    *Main> typeCheck intOmega
    Error: 
    Type error in
    \(x:int).x x
    In expression
    x x
    The type of x: int is not a function type

    *Main> typeCheck (EApp intS intK)
    (int -> int) -> int -> int

    *Main> typeCheck $ EApp (EApp intS intK) intK
    Error: 
    Type error in
    (\(x:int -> int -> int).\(y:int -> int).\(z:int).x z (y z)) (\(x:int).\(y:int).x) (\(x:int).\(y:int).x)
    For expression:
    \(x:int).\(y:int).x
    Cannot match expected type
    int -> int
    against inferred
    int -> int -> int

Z rekonstrukcją typów:

data Exp = EInt Int | EVar Name 
         | ELam Name Exp | EApp Exp Exp

-- Przykładowe lambda-termy


mkI :: Exp
mkI = ELam "x" $ EVar "x"

mkK :: Exp
mkK = ELam "x" $ ELam "y" $ EVar "x"


mkS :: Exp
mkS = ELam "x" $ ELam "y" $ ELam "z"
          $ EApp 
             (EApp (EVar "x") (EVar "z")) 
             (EApp (EVar "y") (EVar "z")) 

k7 :: Exp
k7 = EApp mkK (EInt 7)

-- kombinator omega nie typuje sie w prostym rachunku lambda
mkOmega :: Exp
mkOmega = ELam "x" $ EApp (EVar "x") (EVar "x")

Przykładowa sesja:

*CurryTypes> typeOf k7
Right (b -> int)

*CurryTypes> typeCheck $ EApp (EInt 7) (EInt 7)
Error: 
Type error in
7 7
types 'int' and 'int -> a' do not unify~

*CurryTypes> typeCheck mkOmega
Error: 
Type error in
\x->x x
Cannot construct the infinite type: "a" ~ a -> b

Z polimorficznym let:

data Exp = EInt Int | EVar Name
         | ELam Name Exp | EApp Exp Exp
         | ELet Name Exp Exp -- let x=e1 in e2

letOmega :: Exp
letOmega = ELet "x" (mkI' "z") (EApp (EVar "x") (EVar "x"))
*Main> letOmega
let x = \z->z in x x
*Main> typeCheck letOmega
c -> c