

data T = forall a. MkT a (a->Int)

f :: T -> Int

f (MkT x g) = g x



a

a -> Int

T

T

(a->Int)

(forall a)

(datatype t

X : A;

L : (A --> number);

======

(@p mk_t (@p X L)) : t;

)





(define f

{ t --> number }

(@p mk_t (@p X G)) -> (G X))





(3+) (f (@p mk_t (@p 3 (+ 4))))

7 : number



(4+) (f (@p mk_t (@p a (+ 4))))

error: type error





(7+) (/. X (+ X 3))

#function :LAMBDA [X] [+ X 3] : (number --> number)



(8+) (f (@p mk_t (@p (/. X (+ X 3))

(/. Y (Y 7)) )) )

10 : number



0 Comments:

In Haskell, if we have a type A and a set of functions from A to some other type, we may wish to encapsulate this logic inside of a new general type that does not contain a reference to A. We would like to be able to pass different data and functions to this type constructor and have the dependent functions work across all types, given a proper datatype for our function and data that matches that datatype. Haskell calls this pattern "Existential Data Construction."In A History of Haskell: Being Lazy With Class , Hudak, Hughes, Wadler, and Jones provide the following Haskell datatype as motivation for existential data constructors.Reading this type is fairly straight forward. We say that for any type, we can call a constructor consisting of a value of that type and a function from typeand get a typeback. F then takes this suppliedvalue and uses pattern matching to deconstruct it and forces the call of G on X. Given that G is of typeand X is of type, we can be certain this call will work.I'm belaboring this point because I think it is important to understand that the Qi type system has this expressive power without requiring aexistential constructor in the type. In Qi, we can simply specify some generic type A on the right hand side of the type colon around a variable bound below the sequent refinement rule and rest assured that the type theory will deduce the existence of and proper type for A at compile time.Here is how T looks inside of Qi.We can read this as saying, "If I need to prove something is of type t I must first prove that it is a constructor that has an X of some arbitrary type A and a function L of type A --> number."From there, we can define the function f in a similar manner as the Haskell code.Running this shows how the type system ensures that the A's match up inside the constructor.Like in Haskell, this existential datatype constructor truly covers all types A, as I will show below. In the following code, the type A is bound to (number --> number). Qi, like Haskell, really means it when it says, "any type A".I hope this explanation helps further the understanding of the Qi type system for Haskell users interested in Qi. Feel free to ask any questions you may have.

Post a Comment