2

I'm making a Boolean data, that accepts others types as boolean values, just for fun. I have created the data Boolean, for representing the actual Boolean value, and I have made a class named Booleanizable, that represents values that can be turned into Boolean data. The problem is the following: I want to make a single instance statement for every type that belongs to Num class, instead of making a statement for each type. How do I do that? Just to make it clearer, the code:

module Boolean(
    Boolean,
    true,
    false,
    Booleanizable
) where



data Boolean = Boolean Int

false = Boolean 0
true = Boolean 1

instance Show Boolean where
    show (Boolean 0) = "false"
    show (Boolean 1) = "true"

instance Eq Boolean where
    (Boolean 0) == (Boolean 0) = True
    (Boolean 0) == (Boolean 1) = False
    (Boolean 1) == (Boolean 1) = True
    (Boolean 1) == (Boolean 0) = False



class Booleanizable a where
    toBoolean :: (Booleanizable a) => a -> Boolean

instance Booleanizable Boolean where
    toBoolean (Boolean x) = Boolean x

instance Booleanizable Bool where
    toBoolean True = Boolean 1
    toBoolean False = Boolean 0

And what I'm trying to do:

instance (Num a) => Booleanizable a where
    toBoolean 0 = Boolean 0
    toBoolean _ = Boolean 1

This is the error that appears:

Boolean.hs:37:21:
    Illegal instance declaration for ‘Booleanizable a’
      (All instance types must be of the form (T a1 ... an)
       where a1 ... an are *distinct type variables*,
       and each type variable appears at most once in the instance head.
       Use FlexibleInstances if you want to disable this.)
    In the instance declaration for ‘Booleanizable a’
duplode
  • 33,731
  • 7
  • 79
  • 150
bzim
  • 1,002
  • 9
  • 17
  • 2
    Please show in the question what went wrong in your attempt. (In this case, I was able to correctly guess the error you got, but in other questions it might be trickier to do that.) – duplode Jan 27 '17 at 15:33
  • If the problem is simply the error `Constraint is no smaller than the instance head`, here is a good explanation and solution (use a newtype) - http://stackoverflow.com/a/7198951/348716 – Anupam Jain Jan 27 '17 at 15:55
  • updated the question. It's not that error. Sorry taking so long @duplode – bzim Jan 27 '17 at 16:26
  • 1
    No worries. If you turn on the `FlexibleInstances` extension as the error message suggests, you will get the "Constraint is no smaller [...]" error the other question discusses. – duplode Jan 27 '17 at 16:39

1 Answers1

2

I did three things to make your example working:

1.) At the beginning, I added two Language extensions:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}

2.) I removed the self reference to Booleanizable a in the definition of the class Booleanizable:

Instead of

class Booleanizable a where
    toBoolean :: (Booleanizable a) => a -> Boolean

use

class Booleanizable a where
    toBoolean :: a -> Boolean

3.) I added an additional constraint Eq a to your last instance definition:

instance (Num a, Eq a) => Booleanizable a where
    toBoolean 0 = Boolean 0
    toBoolean _ = Boolean 1
Jogger
  • 1,617
  • 2
  • 12
  • 22