# Difference between revisions of "Type classes are for reusability"

(corrections) |
m (Minor formatting changes) |
||

Line 7: | Line 7: | ||

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

− | + | :{| | |

+ | |<li><p> | ||

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? | 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? | ||

Line 15: | Line 16: | ||

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? | ||

− | + | </p> | |

+ | |- | ||

+ | |<li><p> | ||

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 better be a custom type? | Is the generic pair type the right choice, or should it better be a custom type? | ||

− | + | </p> | |

+ | |- | ||

+ | |<li><p> | ||

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? | ||

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

− | + | </p> | |

+ | |} | ||

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

## Latest revision as of 04:01, 6 April 2021

I see a certain overuse of typeclasses in Haskell libraries.
Type classes are not intended for massive re-use of some short identifier like `fmap`

or in order to access some syntactic sugar
(e.g. do notation or number literals).
Instead type classes exist for writing reusable code.
Functions written using the `Num`

type class like polynomial multiplication work (almost) equally for `Int`

, `Integer`

, `Rational`

, `Float`

, `Double`

and custom number types.
Functions like `mapM`

and `replicateM`

that only need a `Monad`

constraint can be used for all monads including any combination of monad transformers.

Thus, think twice:

Do you really need a

`Num`

instance for a network port, just in order to be able to write`80`

for a port number? How would sensible definitions of`(*)`

would look like? (Actually, it was not necessary to bundle the number literal feature expressed by the`fromInteger`

method with the`(+)`

and`(*)`

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.) Isn't`port 80`

even more comprehensible?Do you really need a

`Functor`

instance for the pair type? 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 a

`Monad`

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