I am a bit confused by the choice of Haskell syntax for type definitions, like in
data Foo = Bar
Namely: does the equality sign here really mean an equality in some subtle sense, or is it just a random notation choice?
For example, in
foo x y = bar y x
the equality is really an equality: if this line is present, foo a b
and bar b a
can be used more or less interchangeably in the program. However, data Foo
and Bar
probably cannot be used interchangeably after data Foo = Bar
.
Whenever i resume my attempts to learn Haskell, i am a bit confused by this IMO counter-intuitive syntax and need to look up the documentation to recall the formats of the LHS and the RHS. Are there any alternative syntaxes for type definitions by any chance?
You’re right that data Foo
(or even Foo
) and Bar
can’t be used interchangeably in Haskell code, but one might argue that type definitions, such as
data List a = Nil | Cons a (List a)
can be transformed into an “equation” of the form List(a) = 1 + a * List(a)
. And you can then start playing with it as if it were an algebraic expression: the equation can be rewritten as List(a) = 1 / (1-a)
, from which List(a) = 1 + a + a*a + a*a*a + ...
. See the paper Seven trees in one for a spectacular application, or this SO question for lots more.
This is all very nice of course, but it’s not going to help you read data declarations better!
For that, you could consider using Generalized Algebraic Datatypes, aka GADTs. One feature of those is that the types of the constructors are explicitly spelled out, making it clear what each constructor’s name is, what types of arguments it takes and what the result type is. And it doesn’t use that pesky =
sign 🙂
Your example would be written as:
data Foo where
Bar :: Foo
the List example I gave above would be:
data List a where
Nil :: List a
Cons :: a -> List a -> List a
and an equivalent of the on-purpose confusingly named data X = X X X | Y
would be:
data X where
X :: X -> X -> X
Y :: X
GADTs, however, are not standard Haskell: they’re a GHC extension, and a pretty recent one (so there might still be some bugs), but for your purpose of having an alternate type definition syntax I think they fit the bill just fine.
2
Foo is a type, Bar is a value. It doesn’t make sense to speak of exchanging them. Rather, the equality sign expresses that type Foo consists of precisely those values on the right; no more and no less.