简体   繁体   中英

What exactly are GHC type coercions?

I have been looking up haskell's core language to understand how it works. One feature that I found during my internet searches were type coercions. I know that they are used to implement GADTs, but I don't understand much else. All descriptions I found online were quite high level for me, although I have a decent understanding of system F, though. Can anyone explain type coercions in an understandable manner to me, please?

Basically Haskell compiles by evaluating to this simple core language. In an effort to keep in simple it's generally not desirable to add constructs like GADTs or type classes directly to the language so instead they are compiled away at the very front end of the compiler into the simpler but more general (and verbose) constructs provided by core. Also keep in mind that Core is typed so we have to make sure we can encode all of these things in a typed way, a significant complication.

In order to encode GADTs they get elaborated to normal data types with existentials and coercions . The basic idea is that a coercion is a type with what is called an equality kind, written t ~ t' . This type is meant to witness evidence that even though we may not know it, t and t' are the same type under the hood. They're passed around just like any other type so there's nothing special in how that is handled. There's also a suite of type constructors for manipulating these types constitution little proofs about equality, like sym :: t ~ t' -> t' ~ t for example. Finally, there is an operator at the term level which takes a term of type t and a type of kind t ~ t' and is typed as a term of type t' . eg cast e T :: t' but this term behaves identically to e . We've just used our proof that t' and t are the same to cast e to make the type checker happy.

That's the basic idea

  • Kinds representing equality
  • Types representing proofs of equality
  • cast at the term level to use these proofs

Also note that by isolating proofs to the type level they cannot end up having a runtime cost as types are going to be erased down the line.

I think a nice reference on all of this is System F with Type Equality Coercions but of course all of SPJ's publications could help.

@jozefg deserves the answer, but here's an example of GADTs desugaring to existential quantification. Not quite Core yet, but a step toward it.

data Foo :: * -> * where
  Bar :: Int -> Foo Int
  Oink :: b -> c -> d -> Foo (f b)

via

data Foo a where
  Bar :: (a ~ Int) => Int -> Foo a
  Oink :: (a ~ f b) => b -> c -> d -> Foo a

to

data Foo a
  = (a ~ Int) => Bar Int
  | forall b c d f. (a ~ f b) => Oink b c d

Courtesy of /u/MitchellSalad on /r/haskell .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM