# 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!