How to write an instance for all types in a class of another type?

I need to define a Truthy type class containing a true method that converts an instance of a type class to a Bool value.

Class type declaration:

 class Truthy a where true :: a -> Bool 

Next, I have to define instances of this class for different types, including list and numeric types. I did this for lists and Int s, but is there a way to do this for all numeric types at the same time?

Based on my Int declaration:

 instance Truthy Int where true = (/=) 0 

I tried to add a class type restriction, 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 number type separately?

+8
haskell
source share
1 answer

It may not help to do your homework, but you can really write such an ad. To do this, enable -XFlexibleInstances . At least in GHC you can do this by putting a pragma at the top of the file:

 {-# LANGUAGE FlexibleInstances #-} 

If you look closely at the error message, it says something like “Use -XFlexibleInstances if you want to disable it.”

In this particular case, you also need to enable UndecideableInstances and OverlappingInstances :

  {-# LANGUAGE FlexibleInstances, UndecideableInstances, OverlappingInstances #-} 

You need FlexibleInstances because the standard Haskell does not allow instances in any form where a type variable appears more than once in the head. This is completely normal - I am one of the most common extensions used (for this question ).

You need UndecideableInstances because declaring your instance could potentially trigger a loop check forever. I think using UndecideableInstances prevents this by limiting how deeply it will be checked when trying to reduce the instance. Usually this - including in this case - is excellent, but theoretically it can do whether a particular program depends on the implementation of type checking. However, it should work in your case.

As the hammar pointed out, you need to enable OverlappingInstances because the "context" of the instance is ignored when checking if they overlap. Context is the Num a bit in this case. Thus, instances - to check for coincidence - are read as instance Truthy a... and overlap with everything. With OverlappingInstances enabled, you just need to have one instance that is most suitable for this.

+10
source share

All Articles