Talk on 2016-01-08 hosted by PLASSE
at ERICA Campus, Hanyang University,
Ansan, Gyeonggi-do, Republic of Korea
best viewed using Chrome at https://slides.com/kyagrd/tiper-erica/
typeCheck :: (Ctx, Exp, Type) -> Bool
typeCheck(gamma, Var x, a) = (x,a) `elem` Gamma
typeCheck(gamma, App e1 e2, b) = case typeInfer(gamma,e1) of
Arr a b -> typeCheck(gamma,e2,a)
_ -> False
typeCheck(gamma, Abs x e, Arr a b) = typeCheck((x,a):gamma, e, b)
typeInfer :: (Ctx, Exp) -> Maybe Type
typeInfer(gamma, Var x) = lookup x gamma
typeInfer(gamma, App e1 e2) = case typeInfer(gamma,e1) of
Arr a b | typeCheck(gamma,e2,a) -> Just b
_ -> Nothing
typeInfer(gamma, Abs x e) = ... -- actually need some more magic here
(Var)
(Abs)
(App)
(Var)
(Abs)
(App)
(Var)
(Abs)
(App)
Specifications for Prototyping / Development
of type system implementations should be
:- set_prolog_flag(occurs_check,true).
:- op(500,yfx,$).
type(C,var(X), T) :- first(X:T,C).
type(C,lam(X,E),A -> B) :- type([X:A|C], E, B).
type(C,E1 $ E2, B) :- type(C,E1,A->B), type(C,E2,A).
first(K:V,[K1:V1|Xs]) :- K = K1, V = V1.
first(K:V,[K1:V1|Xs]) :- K\==K1, first(K:V, Xs).
:- set_prolog_flag(occurs_check,true).
:- op(500,yfx,$).
type(C,var(X), T) :- first(X:T,C).
type(C,lam(X,E),A -> B) :- type([X:A|C], E, B).
type(C,E1 $ E2, B) :- type(C,E1,A->B), type(C,E2,A).
first(K:V,[K1:V1|Xs]) :- K = K1, V = V1.
first(K:V,[K1:V1|Xs]) :- K\==K1, first(K:V, Xs).
?- type([], lam(x,var(x)), A->A). % type checking true . ?- type([], lam(x,var(x)), T). % type inference T = (_G123->_G123) . ?- type([], E, A->A). % type inhabitation E = lam(_G234,var(_G234)) .
:- set_prolog_flag(occurs_check,true).
:- op(500,yfx,$).
type(C,var(X), T1) :- first(X:T,C), instantiate(T,T1).
type(C,lam(X,E), A -> B) :- type([X:mono(A)|C],E,B).
type(C,E1 $ E2, B ) :- type(C,E1,A -> B), type(C,E2,A).
type(C,let(X=E0,E1), T ) :- type(C,E0,A), type([X:poly(C,A)|C],E1,T).
first(K:V,[K1:V1|Xs]) :- K = K1, V=V1.
first(K:V,[K1:V1|Xs]) :- K\==K1, first(K:V, Xs).
instantiate(mono(T),T).
instantiate(poly(C,T),T1) :- copy_term(t(C,T),t(C,T1)).
:- set_prolog_flag(occurs_check,true).
:- op(500,yfx,$).
type(C,var(X), T1) :- first(X:T,C), instantiate(T,T1).
type(C,lam(X,E), A -> B) :- type([X:mono(A)|C],E,B).
type(C,E1 $ E2, B ) :- type(C,E1,A -> B), type(C,E2,A).
type(C,let(X=E0,E1), T ) :- type(C,E0,A), type([X:poly(C,A)|C],E1,T).
first(K:V,[K1:V1|Xs]) :- K = K1, V=V1.
first(K:V,[K1:V1|Xs]) :- K\==K1, first(K:V, Xs).
instantiate(mono(T),T).
instantiate(poly(C,T),T1) :- copy_term(t(C,T),t(C,T1)).
?- copy_term(t([],A->B), t([],T)). T = (_G993->_G994). % fresh vars: _G993 for A, _G994 for B ?- copy_term(t([x:A],A->B), t([x:A],T)). T = (A->_G1024). % fresh vars: _G1024 for B only
-- Tree :: (* -> *) -> * -> *
data Tree c a
= Leaf a -- Leaf :: Tree c a
| Node (c (Tree c a)) -- Node :: (c(Tree c a)) -> Tree c a
type BinTree a = Tree Pair a -- two children on each node
type Pair t = (t,t)
type RoseTree a = Tree List a -- varying number of children
type List a = [a]
:- set_prolog_flag(occurs_check,true).
:- op(500,yfx,$).
kind(KC, var(X), K) :- first(X:T,KC).
kind(KC, F $ G, K2) :- kind(KC,F,K1->K2), kind(KC,G,K1).
kind(KC, A -> B, o) :- kind(KC,A,o), kind(KC,B,o).
type(KC,C,var(X), T1) :- first(X:T,C), instantiate(T,T1).
type(KC,C,lam(X,E), A -> B) :- type([X:mono(A)|C],E,B), kind(KC,A->B,o).
type(KC,C,E1 $ E2, B ) :- type(KC,C,E1,A -> B), type(KC,C,E2,A).
type(KC,C,let(X=E0,E1), T ) :- type(KC,C,E0,A), type(KC,[X:poly(C,A)|C],E1,T).
first(K:V,[K1:V1|Xs]) :- K = K1, V=V1.
first(K:V,[K1:V1|Xs]) :- K\==K1, first(K:V, Xs).
instantiate(mono(T),T).
instantiate(poly(C,T),T1) :- copy_term(t(C,T),t(C,T1)).
?- type(KC,[],lam(x,var(x)),T).
KC = [_G1578:_G1581|_G1584],
T = (var(_G1578)->var(_G1578)) .
% OK, got the most general type at first :)
?- type(KC,[],lam(x,lam(y,var(x))),T). KC = [_G1598:_G1601|_G1604], T = (var(_G1598)->var(_G1598)->var(_G1598)) ; KC = [_G1598:_G1601, _G1598:_G1612|_G1618], T = (var(_G1598)->var(_G1598)->var(_G1598)) ; KC = [_G1598:_G1601, _G1598:_G1612|_G1618], T = (var(_G1598)->var(_G1598)->var(_G1598)) ; KC = [_G1598:_G1601, _G1609:_G1612|_G1618], T = (var(_G1609)->var(_G1598)->var(_G1609))
% Well, the most general type in 4th solution :(
(a specification which kind of works but not really ...)
It gets even more unpleasant for HM + TyCon Poly + Kind Poly
the missing automation tool
in langauge frontend construction
Lack of automated tools for type systems
High development cost to adopt innovations from type theory & PL research
Inflexible and Verbose static type systems in mainstream langauges
Static Types are
considered harmful and
Dynamic Languages rule!
Oops, too painful to refactor/API-update
without static types
Okay, let's add static types
Flow type checker for JavaScript, TypeScript, mypy, Typed Clojure, Typed Lua, ... ..., and all those fancy projects on gradual typing