I'm learning Haskell by reading Learn You a Haskell for Great Good!. Near the end of the Making Our Own Types and Typeclasses section, a class YesNo
is defined to simulate truthiness in languages like javascript:
class YesNo a where
yesno :: a -> Bool
instance YesNo Int where
yesno 0 = False
yesno _ = True
(etc.)
I was trying to flesh out the instances myself as an exercise before reading the reference, and thought I could be clever and define it for all Num
types:
instance (Num a) => YesNo a where
yesno 0 = False
yesno _ = True
I'll skip over how this requires FlexibleInstances
, which I think I've understood between the docs and this answer. Once that's turned on, the compiler complains "The constraint 'Num a' is no smaller than the instance head 'YesNo a'". The answers to this question do a good job of explaining what that means. Using the newtype
solution provided there, I come up with something like
newtype TruthyNum a = TruthyNum a
instance (Num a, Eq a) => YesNo (TruthyNum a) where
yesno (TruthyNum 0) = False
yesno _ = True
But now I have to say e.g. yesno $ TruthyNum 0
instead of yesno 0
.
This doesn't feel right. Is there really no way to cleanly express yesno
for Num
types without writing out an instance for each such type? Or, taking a step back, how would an experienced Haskell hacker come at the premise of "define a typeclass that implements truthiness in the vein of [pick your scripting language]"?