# List instance

### From HaskellWiki

(Category:FAQ) |
(custom newtype is a nice solution in some cases) |
||

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

Line 5: | Line 5: | ||

− | If I have a type class for conversion to a type X: |
+ | If I have a type class for conversion to a type <hask>X</hask>: |

− | <haskell> |
+ | <haskell> |

class C a where |
class C a where |
||

toX :: a -> X |
toX :: a -> X |
||

Line 20: | Line 20: | ||

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

− | but not for Strings, given that they are a synonym for [Char]. Hence: |
+ | but not for Strings, given that they are a synonym for <hask>[Char]</hask>. Hence: |

<haskell> |
<haskell> |
||

Line 35: | Line 35: | ||

</code> |
</code> |
||

− | Is there some type class cleverness that can make this work in haskell |
+ | Is there some type class cleverness that can make this work in Haskell 98? |

− | 98? I can create a new wrapper type for strings: |
||

− | <haskell> |
+ | I'm aware of the approach taken by class <hask>Show</hask> in the prelude, |

− | newtype StringWrap = StringWrap String |
+ | which adds a extra method to the class: |

− | </haskell> |
||

− | |||

− | and write an instance for that, but then I'll have to litter my code |
||

− | with calls to this constructor. |
||

− | |||

− | I'm aware of the approach taken by class Show in the prelude, which |
||

− | adds a extra method to the class: |
||

− | |||

<haskell> |
<haskell> |
||

class C a where |
class C a where |
||

Line 50: | Line 50: | ||

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

− | The trick in the Prelude is that <hask>listToX</hask> has a default implementation. |
+ | First you have to find out, what you really want to do. |

− | If this is not possible in your application then introduce a new class like |
+ | === Define a custom type === |

+ | If you do not need list functions, but e.g. just want to use <hask>String</hask> values as identifiers, |
||

+ | then I advise to just define a custom type: |
||

+ | <haskell> |
||

+ | newtype Identifier = Identifier String |
||

+ | </haskell> |
||

+ | |||

+ | and write the instances you need for that type. |
||

+ | |||

+ | === Keep working with the list (or container) type === |
||

+ | |||

+ | If you need list functions, |
||

+ | then the wrapper approach means that you have to litter your code with calls to the wrapper constructor. |
||

+ | In this case you should stick to the original composed type. |
||

+ | The trick in the Prelude for the <hask>Show</hask> class is, |
||

+ | that <hask>listToX</hask> has a default implementation. |
||

+ | |||

+ | If this is not possible in your application then introduce a new class like |
||

<haskell> |
<haskell> |
||

class Element a where |
class Element a where |
||

listToX :: [a] -> X |
listToX :: [a] -> X |
||

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

− | |||

and define instances like |
and define instances like |
||

− | |||

<haskell> |
<haskell> |
||

instance Element Char where |
instance Element Char where |
||

Line 69: | Line 84: | ||

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

. |
. |
||

+ | |||

+ | More generally, you can introduce a new class like |
||

+ | <haskell> |
||

+ | class IsChar a where |
||

+ | fromChar :: Char -> a |
||

+ | toChar :: a -> Char |
||

+ | instance IsChar Char where |
||

+ | fromChar = id |
||

+ | toChar = id |
||

+ | </haskell> |
||

+ | and then whenever you want to use the "<hask>a</hask>" type as a <hask>Char</hask>, |
||

+ | you just convert it from or to <hask>Char</hask> with <hask>fromChar</hask> or <hask>toChar</hask>, respectively. |
||

+ | |||

+ | === FlexibleInstances === |
||

+ | |||

+ | If none of the above solution is appropriate for you, |
||

+ | then you may choose the <code>FlexibleInstances</code> language extension |
||

+ | that is available in GHC and Hugs. |
||

+ | See http://www.haskell.org/ghc/docs/6.8-latest/html/users_guide/type-class-extensions.html#instance-rules |
||

+ | |||

+ | <haskell> |
||

+ | {-# LANGUAGE FlexibleInstances #-} |
||

+ | instance C [Char] where toX = ... |
||

+ | </haskell> |
||

== Source == |
== Source == |
||

Line 75: | Line 114: | ||

[[Category:FAQ]] |
[[Category:FAQ]] |
||

+ | [[Category:Idioms]] |

## Latest revision as of 13:38, 11 December 2010

## Contents |

## [edit] 1 Question

How to make a list type an instance of some type class in Haskell 98?

Haskell 98 does not support instances on particular composed types like

class C a where toX :: a -> X

I can define instances for

instance C Int where toX = ... instance C Double where toX = ... instance C Tuple where toX = ...

instance C String where toX = ...

results in:

```
```

```
``` Illegal instance declaration for `C String'
(The instance type must be of form (T a b c)
where T is not a synonym, and a,b,c are distinct type variables)
In the instance declaration for `C String'

```
```

Is there some type class cleverness that can make this work in Haskell 98?

I'm aware of the approach taken by classwhich adds a extra method to the class:

class C a where toX :: a -> X listToX :: [a] -> X

## [edit] 2 Answer

First you have to find out, what you really want to do.

### [edit] 2.1 Define a custom type

If you do not need list functions, but e.g. just want to usethen I advise to just define a custom type:

newtype Identifier = Identifier String

and write the instances you need for that type.

### [edit] 2.2 Keep working with the list (or container) type

If you need list functions, then the wrapper approach means that you have to litter your code with calls to the wrapper constructor. In this case you should stick to the original composed type.

The trick in the Prelude for theIf this is not possible in your application then introduce a new class like

class Element a where listToX :: [a] -> X

and define instances like

instance Element Char where listToX = ... instance Element a => C [a] where toX = listToX

.

More generally, you can introduce a new class like

class IsChar a where fromChar :: Char -> a toChar :: a -> Char instance IsChar Char where fromChar = id toChar = id

### [edit] 2.3 FlexibleInstances

If none of the above solution is appropriate for you,
then you may choose the `FlexibleInstances`

language extension
that is available in GHC and Hugs.
See http://www.haskell.org/ghc/docs/6.8-latest/html/users_guide/type-class-extensions.html#instance-rules

{-# LANGUAGE FlexibleInstances #-} instance C [Char] where toX = ...

## [edit] 3 Source

http://www.haskell.org/pipermail/haskell-cafe/2007-May/025742.html