Skip to main content
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

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 questionthis 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.

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.

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.

Source Link
yatima2975
  • 216
  • 1
  • 3

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.