This is a good and well-written article, but it's worth noting that I think many of the ideas here cut slightly against the grain of current Haskell best practices. Which is not to say any specific part is right, but for example the entire discussion on QuickCheck is hard to really make sense of and arbitrary is a famously good use of type classes.
Probably the most countercultural paragraph is the paragraph on recommending you make a fresh type rather than reuse an existing type. I think that you lose so many useful operations eschewing maybe for your uniquely named Maybe [1] that a type alias is probably a much better call there, and also captures what you meant more generically. Further, stuff like Maybe over a more specific instance works much better with valuable tools like Compose.
Similarly, the redundant constraint on Empty is the sort of thing that will only trip you up in the real world.
All in all, great article tho.
[1]: People underestimate the compiler cost of deriving instances. It adds up very fast if you derive lots of functors and foldables in your quest for unique names everywhere.
Thanks for your commentary too. I’m starting to learn Haskell, and the nature of the language seems to lead to less “best practices” articles out there.
Seeing knowledgeable people comment on things written by other knowledgeable people seems to be the best way to learn how Haskell is done in the wild (i.e. anything outside the text I’m learning Haskell from at the moment)!
There's quite a few people who don't like arbitrary, though, aren't there? Hedgehog is growing in popularity as an alternative to the quickcheck approach.
>the entire discussion on QuickCheck is hard to really make sense of and arbitrary is a famously good use of type classes
I found it understandable but for me the issue was: all the problems that author pointed out are true but you're not forced to make an instance of Arbitrary. I rarely do in my tests. But some times it really does make sense and in those cases it's nice to have.
> People underestimate the compiler cost of deriving instances. It adds up very fast if you derive lots of functors and foldables in your quest for unique names everywhere.
Do you pay this price when you derive via a `newtype`? Or does GHC figure out that the instance it would write out would be identical (modulo coercions)?
From the earliest days, amateurs instruct computers, while professionals write executable stories. I loved reading the projection of this quip into Haskell.
I found the paragraph about iterating with list comprehensions very illuminating. As someone who is just starting to learn Haskell, deciding when not to use map / filter is something where my intuitions regularly seem to be off.
I like the fact (that I didn't know before) that you can use refutable patterns in the way shown here, as filters in a list comprehension. That feels almost like logic programming.
This is very weird Haskell. The fizz buzz example concatenating strings where an alternative would fit and the pointful point free example for instance.
[+] [-] KirinDave|8 years ago|reply
Probably the most countercultural paragraph is the paragraph on recommending you make a fresh type rather than reuse an existing type. I think that you lose so many useful operations eschewing maybe for your uniquely named Maybe [1] that a type alias is probably a much better call there, and also captures what you meant more generically. Further, stuff like Maybe over a more specific instance works much better with valuable tools like Compose.
Similarly, the redundant constraint on Empty is the sort of thing that will only trip you up in the real world.
All in all, great article tho.
[1]: People underestimate the compiler cost of deriving instances. It adds up very fast if you derive lots of functors and foldables in your quest for unique names everywhere.
[+] [-] davidmr|8 years ago|reply
Seeing knowledgeable people comment on things written by other knowledgeable people seems to be the best way to learn how Haskell is done in the wild (i.e. anything outside the text I’m learning Haskell from at the moment)!
[+] [-] moomin|8 years ago|reply
[+] [-] alien_at_work|8 years ago|reply
I found it understandable but for me the issue was: all the problems that author pointed out are true but you're not forced to make an instance of Arbitrary. I rarely do in my tests. But some times it really does make sense and in those cases it's nice to have.
[+] [-] harpocrates|8 years ago|reply
Do you pay this price when you derive via a `newtype`? Or does GHC figure out that the instance it would write out would be identical (modulo coercions)?
[+] [-] ByzantineO6|8 years ago|reply
[+] [-] z5h|8 years ago|reply
[+] [-] samwestdev|8 years ago|reply
[+] [-] nocobot|8 years ago|reply
[+] [-] tom_mellior|8 years ago|reply
[+] [-] rs86|8 years ago|reply
[+] [-] chopin|8 years ago|reply
[+] [-] Bootvis|8 years ago|reply