2016-02-18 Tuesday (목) Milestone Talk
한국정보과학회 프로그래밍언어연구회 동계 워크숍 (KIISE SIGPL Winter Workshop 2016)
전주 전북대학교 박물관 (Jeonbuk National University Museum, Jeonju, Jeollabuk-do, Korea)
best viewed on Chrome, available online at https://slides.com/kyagrd/tiper-sigpl2016ko/
Type Systems being re-invented
Problem & Solution?
Lack of automated tools for building type systems
High development cost to adopt innovations from type theory & PL research
Inflexible and/or Verbose static type systems in mainstream langauges
Static Types
considered harmful, let's
use Dynamic Languages!
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
trending in the real world
(highly Polymorphic)
(good Type Inference)
the missing automation tool
in langauge frontend construction
tyChk :: (Ctx, Exp, Type) -> Bool
tyChk(g, Var x, a) = (x,a) `elem` g
tyChk(g, Abs x e, Arr a b) = tyChk((x,a):g, e, b)
tyChk(g, App e1 e2, b) = case tyInf(g,e1) of { Arr a b -> tyChk(g,e2,a)
; _ -> False }
tyInf :: (Ctx, Exp) -> Maybe Type
tyInf(g, Var x) = lookup x gamma
tyInf(g, Abs x e) = ... -- actually need some more magic here
tyInf(g, App e1 e2) = case tyInf(gamma,e1) of { Arr a b
| tyChk(g,e2,a) -> Just b
; _ -> Nothing }
(Var)
(Abs)
(App)
(Var)
(Abs)
(App)
(Var)
(Abs)
(App)
:- 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).
incrementally builds up a substitution
can inspect intermediate results (not a black box)
basic building block for type inference algorithms
Inductive Definitions in Interactive Theorem Provers
Logic Programming
Constraint Solvers / Automated Theorem Provers
No semantics, hard to inspect intermediate result
Solvers are usually difficult to extend
:- 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, _G994 for A, 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]
HM only supports type polymorphism such as (1) but
not higher-kinded poly. such as (2) supported in Haskell
:- 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)).
(a specification which kind of works but not really ...)
Note. Not a correct spec. for TyCon Poly. but just for demo.
The "instantiate" predicate should be modified too.
(a specification which kind of works but not really ...)
?- 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 :(
gets even more unpleasant for HM + TyCon Poly + Kind Poly + ...
continuous integration by multiple iterations of (a) and (b)
Embedded DSL for LP
miniKanren and microKanren ( http://miniKanren.org ) ported to more than a dozen of programming languages
Coinductive flavors of LP
Type Inference by Coinductive Logic Programming
(Ancona, Lagorio, Zucca 2009) in post TYPES 2008
Proof Relevant Corecursive Resolution in FLOPS 2016
(Fu, Komendantskaya, Schrijvers, Pond 2016)
Delimited Continuations for Prolog in ICLP 2013
(Schrijvers, Demoen, Desouter, Wielemaker 2013)
Membership-Constraints and Complexity in Logic Programming with Sets (Stolzenburg 1996) in FroCoS 1996
Executable Specification of Static Semantics note: Typol
(Despeyroux. 1984) in Semantics of Data Types 1984
Extraction of Strong Typing Laws from Action Semantics Definitions (Doh, Schmidt. 1992) in ESOP 1992
Type Inference with Constrained Types note: HM(X)
(Odersky, Sulzmann, Wehr. 1999) TAPOS, 5(1):33-55
Type System for the Massses in Onward 2015
(Grewe, Erdweg, Wittmann, Mezini 2015)
And there are more frameworks for type checker development
TyS: a framework to facilitate the dev. of OO type checkers
Typical: Taking the Tedium Out of Typing