On May 10, 2005, at 4:14 AM, Bo Herlin wrote:

> Well, part of what I was doing was experimenting with what a library like
> this should look like, even more than what it should do. For some reason,
> I kind of like writing this:
>
> *Math.Prime> is Prime 42
> False
>
> instead of this:
>
> *Math.Prime> isPrime 42
> False


Great! I like this a LOT.

Why not use a function?

What's wrong with a function?

There no need to go leaping for a multiparameter type class with a functional dependency! Just use a function.

[With apologies to John Cleese]

In all seriousness, I loathe this style.  Let me tell you why:

* We are introducing types whose only purpose is to stand for a single function.

* Declaring a property used to take one line---a function declaration. Now it takes a minimum of three:
- a bogus type declaration for Primes
- an instance declaration
- the actual declaration for "is".


* The use of multiparameter type classes leads to relatively more obscure error messages and clunky type signatures with bogus type parameters.

* It's not Haskell 98, and an acceptable (or even preferable) solution exists which is.

* There's no equivalent of lambda here---we can't write anonymous properties. I list this last, as some may consider it a disadvantage.


When using fancy type-system footwork, I suggest the following questions (which I ask myself, too):


* Can I replace one or more parameters to my methods with a suitably-typed call to "undefined"? This often means I'm being to clever for my own good. Perhaps that argument could be eg. a phantom parameter of another type.

* What would happen if I used a record instead of a class declaration? The result might look pretty similar on the page, but it might be H98. If the class has 0 or 1 method, you don't even need a record---you can pass things directly.

* Could I use a newtype rather than a separate type parameter? Sometimes this is acceptable, sometimes it's better, and sometimes (in the case of the NumberTheory library, I suspect) it's not what you actually want.

* How much worse would it look if I just used H98? Sometimes it won't be possible at all. Sometimes it just requires a change of perspective to make it look very pretty. And often a bunch of fancy footwork at the type level leads to a solution that I didn't anticipate---and which fits nicely in H98.


I also have an informal mental hierarchy of complexity of types---though others may find this more controversial:
* Simple algebraic types
* H98 type classes
* Fancier instance heads (but still single-parameter, non-overlapping)
* Existential and local universal quantification
* GADTs (I'm still uncertain about this judgement, but they seem to be less troublesome than...)
* Multiparameter type classes



-Jan-Willem Maessen

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to