Towards Interface Types for Haskell
Work in Progress
Peter Thiemann
Joint work with Stefan Wehr Universit ¨at Freiburg, Germany
What is a type class?
I A type class is a signature of an abstract data type. I But where is the abstract type?
What is a type class?
I A type class is a signature of an abstract data type. I But where is the abstract type?
What is a type class?
I A type class is a signature of an abstract data type.
Example: HDBC interface
I Signature of abstract data type
moduleHDBCwhere classConnection connwhere
exec :: conn−>String−>IO QueryResult
I Implementation of abstract data type
modulePostgreSQLDBwhere importHDBC
instanceConnection PostgreSQLConnectionwhere exec = pgsqlExec
I Extending the abstract data type
classConnection conn =>BetterConnection connwhere
Example: HDBC interface
I Signature of abstract data type
moduleHDBCwhere classConnection connwhere
exec :: conn−>String−>IO QueryResult
I Implementation of abstract data type
modulePostgreSQLDBwhere importHDBC
instanceConnection PostgreSQLConnectionwhere exec = pgsqlExec
I Extending the abstract data type
classConnection conn =>BetterConnection connwhere
Example: HDBC interface
I Signature of abstract data type
moduleHDBCwhere classConnection connwhere
exec :: conn−>String−>IO QueryResult
I Implementation of abstract data type
modulePostgreSQLDBwhere importHDBC
instanceConnection PostgreSQLConnectionwhere exec = pgsqlExec
I Extending the abstract data type
classConnection conn =>BetterConnection connwhere
Why want an abstract type?
I Encapsulation
What is a good type forconnect? I Can do with
connectWith :: URL−>(forallc. Connection c =>c−>IO a)−>IO a
I but: requires user code in continuation I no “connection value” that can be stored I not possible as member of class Connection I How about
connect :: URL−>IO Connection
Why want an abstract type?
I Encapsulation
What is a good type forconnect?
I Can do with
connectWith :: URL−>(forallc. Connection c =>c−>IO a)−>IO a
I but: requires user code in continuation I no “connection value” that can be stored I not possible as member of class Connection I How about
connect :: URL−>IO Connection
Why want an abstract type?
I Encapsulation
What is a good type forconnect?
I Can do with
connectWith :: URL−>(forallc. Connection c =>c−>IO a)−>IO a
I but: requires user code in continuation I no “connection value” that can be stored I not possible as member of class Connection I How about
connect :: URL−>IO Connection
Interfaces for Haskell
A Design ProposalI Type classI⇒interface typeI
I TypeIisexistsc. (I c) =>c
I Subtyping for interface types ifIis a subclass ofJ,
thenI≤J
I Subtyping for instance types ift is an instance type ofJ, thent≤J
I Introduction by type annotation ⇒no new syntax
Interfaces for Haskell
A Design ProposalI Type classI⇒interface typeI
I TypeIisexistsc. (I c) =>c
I Subtyping for interface types ifIis a subclass ofJ,
thenI≤J
I Subtyping for instance types ift is an instance type ofJ, thent≤J
I Introduction by type annotation ⇒no new syntax
Interfaces for Haskell
A Design ProposalI Type classI⇒interface typeI
I TypeIisexistsc. (I c) =>c
I Subtyping for interface types ifIis a subclass ofJ,
thenI≤J
I Subtyping for instance types ift is an instance type ofJ, thent≤J
I Introduction by type annotation
Example Patterns of Use
I Create a connection
betterConnect :: URL−>IO BetterConnection
betterConnect url =
doc<−pgconnect url
−−c :: PGSQLConnection return (c :: BetterConnection) I Wrapper
dbwrapper :: URL−>(URL−>IO Connection)−>IO Result
dbwrapper url connect =
doc<−connect url
do something c
... dbwrapper url betterConnect ... I Worker
worker :: Connection−>IO Result
withBetterConnection :: (BetterConnection−>IO a)−>IO a
Collecting the Pieces
Surprise!
Collecting the Pieces
Existential Types in HaskelldataT Connectionwhere
T Connection ::forallconn.
Connection conn =>conn−>T Connection
dataT BetterConnectionwhere
T BetterConnection ::forallconn.
BetterConnection conn =>conn−>T BetterConnection
instanceT Connection Connectionwhere... instanceT Connection BetterConnectionwhere... instanceT BetterConnection BetterConnectionwhere...
I Tagged existentials
Collecting the Pieces
Subtyping in HaskellI There is no subtyping in Haskell!
I But, there is the generic instance relation: forallc. BetterConnection c =>c−>T
forallc. Connection c =>c−>T
I And there is the double negation equivalence: existsa. P =>T=(foralla. P =>T−>x)−>x
I Approach: Translate existential types to (higher-rank) polymorphism where possible
Collecting the Pieces
Subtyping in HaskellI There is no subtyping in Haskell!
I But, there is the generic instance relation:
forallc. BetterConnection c =>c−>T
forallc. Connection c =>c−>T
I And there is the double negation equivalence: existsa. P =>T=(foralla. P =>T−>x)−>x
I Approach: Translate existential types to (higher-rank) polymorphism where possible
Collecting the Pieces
Subtyping in HaskellI There is no subtyping in Haskell!
I But, there is the generic instance relation:
forallc. BetterConnection c =>c−>T
forallc. Connection c =>c−>T
I And there is the double negation equivalence:
existsa. P =>T=(foralla. P =>T−>x)−>x
I Approach: Translate existential types to (higher-rank) polymorphism where possible
Collecting the Pieces
Subtyping in HaskellI There is no subtyping in Haskell!
I But, there is the generic instance relation:
forallc. BetterConnection c =>c−>T
forallc. Connection c =>c−>T
I And there is the double negation equivalence:
existsa. P =>T=(foralla. P =>T−>x)−>x
I Approach: Translate existential types to (higher-rank) polymorphism where possible
Example Translation
Create a ConnectionbetterConnect :: URL−>IO BetterConnection
betterConnect url =
doc<−pgconnect url
−−c :: PGSQLConnection return (c :: BetterConnection)
translates to
betterConnect’ :: URL−>IO T BetterConnection
betterConnect’ url =
doc<−pgconnect url
Example Translation
Wrapperdbwrapper :: URL−>(URL−>IO Connection)−>IO Result
dbwrapper url connect =
doc<−connect url
do something c
... dbwrapper url betterConnect ...
translates to
dbwrapper’ :: URL−>forallc. Connection c =>(URL−>IO c)−>IO Result
dbwrapper’ url connect =
doc<−connect url
do something c
betterConnect’ :: URL−>IO T BetterConnection
Example Translation
Workerworker :: Connection−>IO Result
withBetterConnection :: (BetterConnection−>IO a)−>IO a
... withBetterConnection worker ...
translates to
worker’ ::forallc . Connection c =>c−>IO Result
withBetterConnection’ :: (forallc. BetterConnection c =>c−>IO a)−>IO a
Interfaces for Haskell
Translational ApproachI Starting point: Haskell with higher-rank polymorphism (as in current implementations)
I Extensions:
Extended syntax of types
s,t::=· · · |I Typing rules (E-ann’) P|Γ` 0e:s s≤t P |Γ`0 (e::t) :t (E-sub’) P|Γ` 0e:s s≤0t P |Γ`0 e:t
Subtyping
(S-refl) t≤t (S-trans) t1≤t2 t2≤t3 t1≤t3 (S-subclass) I⇒C J I≤J (S-instance) m∈I J m≤J (S-tycon) s≤t T s≤T t (S-fun) t1≤s1 s2≤t2 s1−→s2≤t1−→t2 (S-qual) s≤t ∀a.Q⇒s≤∀a.Q⇒tRestricted Subtyping
t≤0t t1≤ 0t 2 t2≤0t3 t1≤0t3 s≤0t T s≤0T t t1≤s1 s2≤0t2 s1−→s2≤0t1−→t2Restricted subtyping vs generic instance Lemma
If s≤0t and s;0 s0 and t ;0 t0then
Restricted Subtyping
t≤0t t1≤ 0t 2 t2≤0t3 t1≤0t3 s≤0t T s≤0T t t1≤s1 s2≤0t2 s1−→s2≤0t1−→t2Restricted subtyping vs generic instance Lemma
If s≤0t and s;0 s0 and t ;0 t0then
Translation of Types
a;0 2/a ti ; 0 C0 i/ti0 T t;0mapT(λx.Ci0[x])2/T t0 t1;π1]t10 t2;0C2/t20 t1−→t2;0 λx.C2[2x]/π1(t10 −→t 0 2) I;0 KI2/WI t;0C0/t0 ∀a.P ⇒t;0C0/∀a.P ⇒t0 a;∅]a t;π ]t 0 T t;π ]T t0 t1;π1]t10 t2;π2]t20 t1−→t2;π2] π1(t10 −→t20) I;∀c.Ic⇒]c t ;π ]t 0 ∀a.Q⇒t ;π ]∀a.Q⇒t0Translation of Terms
x ,→x e,→e 0 λx.e,→λx.e0 e,→e0 s;∅]s0 λ(x ::s).e,→λ(x ::s0).e0 e,→e0 s;∀c.Q]s0 s;0C0/s00 λ(x ::s).e,→Λc(Q).λ(y ::s0).(λ(x ::s00).e0) (C0[y]) f ,→f0 e,→e0 f e,→f0e0 e,→e0 f ,→f0 letx =einf ,→letx =e0inf0 e,→e0 s ;0 C0/s0 (e::s),→(C0[e0] ::s0)Results
I LetP|Γ0 `e0 :s0 be the typing judgment for Haskell with higher-rank qualified polymorphism.
I IfP|Γ`0 e:s,s;0 s0,Γ;0Γ0, ande,→e0, then
Conclusions
I Type translation maps subtyping to generic instantiation
I Term translation is typing preserving
I Both are purely syntactic
I Q: Is the term translation meaning preserving?
I Q: Is the translated term amenable to type inference?
I Q: Can we do direct inference and translation to F2?
I If Java interface types make sense for Haskell, then how about type classes for Java? ⇒JavaGI @ECOOP’07
Conclusions
I Type translation maps subtyping to generic instantiation
I Term translation is typing preserving
I Both are purely syntactic
I Q: Is the term translation meaning preserving?
I Q: Is the translated term amenable to type inference?
I Q: Can we do direct inference and translation to F2?
I If Java interface types make sense for Haskell, then how about type classes for Java? ⇒JavaGI @ECOOP’07
Digression: The ML way
1 signatureCONNECTION = 2 sig typeconnection
3 valexec : connection−>string−>queryresult
4 end
5
6 signatureBETTERCONNECTION = 7 sig typeconnection
8 valexec : connection−>string−>queryresult
9 valnotify : connection−>string−>unit
10 end
11
12 structurePostgreSQL : BETTERCONNECTION = 13 struct typeconnection = postgreSQLConnection
14 valexec = ...
15 valnotify = ...
16 end
I Encapsulation and Extensibility:
BETTERCONNECTION<: CONNECTION