I started reading about GADT in Haskell Wiki but didn't feel quite comfortable understanding it. Do you recommend a specific book chapter or a blog post explaining GADT for a Haskell beginner?
I like the example in the GHC manual. It's simple, and it illustrates some key points:
GADTs let you use Haskell's type system to model the type system of a language you're implementing (the "object language")
This allows Haskell's static checking to assert that your "compiler passes" or what-not are type preserving. Functions taking object-language terms can assume those terms are well-typed. Functions returning object-language terms are required to produce well-typed terms.
Pattern matching a GADT constructor causes type refinement.
eval
has typeTerm a -> a
overall, but the right-hand side foreval (Lit i)
has typeInt
, because the left-hand constructor had typeTerm Int
.The Haskell system doesn't care what types you give your GADT constructors. We could just as easily make every constructor in
data Term a
give a result of typeTerm a
, orTerm Bool
, and thedata
definition would still go through. But we wouldn't be able to writeeval :: Term a -> a
. You choose the GADT "tag types" to model your problem, so that the useful functions you want to write are well-typed.
Apfelmus has made video tutorial for GADTs which might be helpful.