# Type classes are for reusability

### From HaskellWiki

(Difference between revisions)

(good and bad examples of type class use) |
(corrections) |
||

Line 1: | Line 1: | ||

I see a certain overuse of typeclasses in Haskell libraries. |
I see a certain overuse of typeclasses in Haskell libraries. |
||

− | Type classes are not intended for massive re-use of some short identifier or in order to access some [[syntactic sugar]] |
+ | Type classes are not intended for massive re-use of some short identifier like <hask>fmap</hask> or in order to access some [[syntactic sugar]] |

− | (e.g. [[do notation considered harmful|do notation]] or [[number literal]]s. |
+ | (e.g. [[do notation considered harmful|do notation]] or [[number literal]]s). |

Instead type classes exist for writing reusable code. |
Instead type classes exist for writing reusable code. |
||

Functions written using the <hask>Num</hask> type class like polynomial multiplication work (almost) equally for <hask>Int</hask>, <hask>Integer</hask>, <hask>Rational</hask>, <hask>Float</hask>, <hask>Double</hask> and custom number types. |
Functions written using the <hask>Num</hask> type class like polynomial multiplication work (almost) equally for <hask>Int</hask>, <hask>Integer</hask>, <hask>Rational</hask>, <hask>Float</hask>, <hask>Double</hask> and custom number types. |
||

Line 8: | Line 8: | ||

Thus, think twice: |
Thus, think twice: |
||

− | Do you really need a <hask>Num</hask> instance for a network port, just in order to be able to write <hask>80</hask> for a port number? |
+ | Do you really need a <hask>Num</hask> instance for a [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053043.html network port], just in order to be able to write <hask>80</hask> for a port number? |

− | How would sensible definitions of <hask>(+)</hask> would look like? |
+ | How would sensible definitions of <hask>(*)</hask> would look like? |

(Actually, it was not necessary to bundle the number literal feature expressed by the <hask>fromInteger</hask> method |
(Actually, it was not necessary to bundle the number literal feature expressed by the <hask>fromInteger</hask> method |
||

with the <hask>(+)</hask> and <hask>(*)</hask> operations, |
with the <hask>(+)</hask> and <hask>(*)</hask> operations, |
||

− | and indeed [[NumericPrelude]] chooses a different set of operations. |
+ | and indeed [[Numeric Prelude]] chooses a different set of operations. |

But it is generally accepted that number literals are reserved for objects that allow some sort of arithmetics.) |
But it is generally accepted that number literals are reserved for objects that allow some sort of arithmetics.) |
||

Isn't <hask>port 80</hask> even more comprehensible? |
Isn't <hask>port 80</hask> even more comprehensible? |
||

Line 18: | Line 18: | ||

Do you really need a <hask>Functor</hask> instance for the pair type? |
Do you really need a <hask>Functor</hask> instance for the pair type? |
||

What distinguishes the second member from the first member? |
What distinguishes the second member from the first member? |
||

− | Is the generic pair type the right choice, or should it be better a custom type? |
+ | Is the generic pair type the right choice, or should it better be a custom type? |

Do you really need a <hask>Monad</hask> instance for writing something to a stream? |
Do you really need a <hask>Monad</hask> instance for writing something to a stream? |
||

Or did you define the instance only for the do notation? |
Or did you define the instance only for the do notation? |
||

− | Ever considered a [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053317.html monoid] instead? |
+ | Please, give the [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053317.html monoid] a try! |

## Latest revision as of 15:59, 20 January 2009

I see a certain overuse of typeclasses in Haskell libraries.

Type classes are not intended for massive re-use of some short identifier likefmap

(e.g. do notation or number literals). Instead type classes exist for writing reusable code.

Functions written using theNum

Int

Integer

Rational

Float

Double

mapM

replicateM

Monad

Thus, think twice:

Do you really need aNum

80

(*)

fromInteger

(+)

(*)

and indeed Numeric Prelude chooses a different set of operations. But it is generally accepted that number literals are reserved for objects that allow some sort of arithmetics.)

Isn'tport 80

Functor

What distinguishes the second member from the first member? Is the generic pair type the right choice, or should it better be a custom type?

Do you really need aMonad

Or did you define the instance only for the do notation? Please, give the monoid a try!