# Data declaration with constraint

### From HaskellWiki

(Difference between revisions)

(maybe multi-parameter type classes are a way out) |
Artyom Kazak (Talk | contribs) m (→Solution: Change the link again) |
||

(6 intermediate revisions by 4 users not shown) | |||

Line 7: | Line 7: | ||

data C a => T a = Cons a | data C a => T a = Cons a | ||

</haskell> | </haskell> | ||

− | and I hoped that now the type checker knows | + | |

− | that every value of type <hask>T a</hask> satisfies the type constraint on <hask>a</hask>. | + | and I hoped that now the type checker knows that every value of type <hask>T a</hask> satisfies the type constraint on <hask>a</hask>. |

I like to declare an instance for an type constructor class for the type constructor <hask>T</hask> | I like to declare an instance for an type constructor class for the type constructor <hask>T</hask> | ||

but its methods require type constraints that depend on the particular type constructor <hask>T</hask>. | but its methods require type constraints that depend on the particular type constructor <hask>T</hask>. | ||

− | + | For example: | |

<haskell> | <haskell> | ||

instance Vector T where | instance Vector T where | ||

Line 20: | Line 20: | ||

=== Answer === | === Answer === | ||

− | + | In Haskell 98, only functions can have type constraints. | |

The type constraint of a <hask>data</hask> only refers to the constructors. | The type constraint of a <hask>data</hask> only refers to the constructors. | ||

− | The designers of Haskell 98 do now think, that it was a bad decision to allow constraints on constructors. | + | The designers of Haskell 98 do now think, that it was a bad decision to allow constraints on constructors. GHC as of version 7.2 disallows them by default (turn back on with <code>-XDatatypeContexts</code>). |

== Solution == | == Solution == | ||

− | + | You could use ghc's [https://wiki.haskell.org/GADTs_for_dummies Generalised Algebraic Data Structures (GADTs)] to add an implicit context to the data constructors: | |

− | + | ||

+ | <haskell> | ||

+ | data T a where | ||

+ | Cons :: C a => a -> T a | ||

+ | </haskell> | ||

+ | |||

+ | This way, functions using <hask>T</hask> no longer need a constraint. Instead, constructing a <hask>T a</hask> using <hask>Cons</hask> needs a <hask>C a</hask> context, and when something pattern matches a <hask>Cons x</hask>, the context comes with it. | ||

− | + | There has been some discussion about whether it is sensible to want this. | |

− | + | ||

+ | A Haskell 98 workaround is to use [[multi-parameter type class]]es, where <hask>T a</hask> and <hask>a</hask> are separate arguments. | ||

== See also == | == See also == |

## Latest revision as of 23:26, 19 September 2016

## Contents |

## [edit] 1 Problem

### [edit] 1.1 Question

I have declared

data C a => T a = Cons a

T a

a

T

T

For example:

instance Vector T where add (Cons x) (Cons y) = Cons (x+y) -- requires Num constraint on type a

### [edit] 1.2 Answer

In Haskell 98, only functions can have type constraints.

The type constraint of adata

The designers of Haskell 98 do now think, that it was a bad decision to allow constraints on constructors. GHC as of version 7.2 disallows them by default (turn back on with `-XDatatypeContexts`

).

## [edit] 2 Solution

You could use ghc's Generalised Algebraic Data Structures (GADTs) to add an implicit context to the data constructors:

data T a where Cons :: C a => a -> T a

T

T a

Cons

C a

Cons x

There has been some discussion about whether it is sensible to want this.

A Haskell 98 workaround is to use multi-parameter type classes, whereT a

a

## [edit] 3 See also

- Henning Thielemann in Haskell-Cafe: Context for type parameters of type constructors
- Mark Nicholls in Haskell-Cafe: nice simple problem for someone struggling....