I have to define a type class Truthy
which contains a method true
converting an instance of the type class to a Bool
value.
My type class declaration:
class Truthy a where
true :: a -> Bool
Next, I have to define instances of this class for various types, including list and numeric types. I have done it for lists and Int
s, but is there a way to do it for all numeric types at once?
Based on my Int declaration:
instance Truthy Int where
true = (/=) 0
I have tried adding type class constraint, but it does not work:
instance (Num a) => (Truthy a) where
true = (/=) 0::a
If there is a way to do this similar to what I had in mind, or should I just define it for each numeric type separately?
This might not help for homework, but you actually can write a declaration like that. You just have to enable -XFlexibleInstances
to do so. At least in GHC, you can do this by putting a pragma at the top of your file:
{-# LANGUAGE FlexibleInstances #-}
If you look closely at the error message you got, it said something like "Use -XFlexibleInstances if you want to disable this.".
In this particular case, you would also need to enable UndecidableInstances
and OverlappingInstances
:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
You need FlexibleInstances
because standard Haskell does not allow instances in any form where the type variable appears more than once in the head. This is completely fine--I it is one of the most common extensions used (as per this question).
You need UndecidableInstances
because your instance declaration could potentially cause the type checker to loop forever. I think using UndecidableInstances
prevents this by limiting how deeply it will check when trying to reduce the instance. This is usually--including in this case--fine, but could theoretically make whether a particular program passes the type checks implementation dependent. Still, it should work in your case.
As hammar pointed out, you need to enable OverlappingInstances
because the "context" of the instance is ignored when checking whether they overlap. The context is the Num a
bit in this case. So the instances--for checking if it overlaps--is read as instance Truthy a...
and overlaps with everything. With OverlappingInstances
enabled, you just need to have one instance that is the most specific for this to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With