Reputation: 65
data Bit = One
| Zero
deriving Show
type Bits = [Bit]
bits2String :: Bits -> String
bits2String [] = ""
bits2String (x:xs) | x == One = "1" ++ bits2String xs
| x == Zero = "0" ++ bits2String xs
This Code causes following error message:
No instance for (Eq Bit) arising drom a use of '=='
For this error you can find a lot of solutions on SO. They always say you need to add Eq like that:
bits2String :: (Eq Bit) => Bits -> String
bits2String [] = ""
bits2String (x:xs) | x == One = "1" ++ bits2String xs
| x == Zero = "0" ++ bits2String xs
But this doesnt work for me and causes following error
Non type-variable argument in the constraint: Eq Bit
(Use FlexibleContexts to permit this)
{-# LANGUAGE FlexibleContexts #-} doesnt work either.
Upvotes: 1
Views: 181
Reputation: 18249
The original error message is the key one:
No instance for (Eq Bit) arising drom a use of '=='
This arises because you are using the ==
operator, which is only available for instances of the Eq
typeclass - and you haven't given such an instance.
That's easily fixed though. For one you can easily provide the instance manually:
instance Eq Bit where
One == One = True
Zero == Zero = True
_ == _ = False
I wouldn't recommend that you do that though. You can ask Haskell to generate that exact instance for you by simply adding a deriving
clause to the type definition. In fact you're already using one, so you can just add Eq
to the list of instances you want to derive:
data Bit = One
| Zero
deriving (Show, Eq)
Adding this instance is a good idea in general, because you might well need to compare Bit
s for equality at some point, especially when working with lists of them - many list functions such as elem
depend on Eq
instances for their members.
But you can rewrite your bits2String
function to not need an Eq
instance at all, by pattern matching on the two data constructors:
bits2String :: Bits -> String
bits2String [] = ""
bits2String (One:xs) = "1" ++ bits2String xs
bits2String (Zero:xs) = "0" ++ bits2String xs
In fact, you've basically reimplemented the map
function here, so what I would likely do is to define:
bitToChar :: Bit -> Char
bitToChar Zero = '0'
bitToChar One = '1'
(especially as it's the kind of general utility function that you may well want for other things)
and then
bits2String = map bitToChar
None of those require an Eq
instance - but it's likely a good idea to derive it anyway, for the reasons I mentioned.
Upvotes: 2
Reputation: 476574
You make use of x == Zero
, so of the (==) :: Eq a => a -> a -> Bool
function, but you did not make Bit
an instance of Eq
. You can do so by adding it to the deriving
clause, such that Haskell can automatically implement an instance
of Eq
for your Bit
data type:
data Bit = One
| Zero
deriving (Eq, Show)
By default two items are the same if the data constructor is the same, and the parameters (but here your data constructors have no parameters, so it will only check equality of the data constructors).
That being said, you do not need these to be an instance of Eq
, you can use pattern matching instead. Indeed:
bits2String :: Bits -> String
bits2String = map f
where f Zero = '0'
f One = '1'
Here we make use of map :: (a -> b) -> [a] -> [b]
to convert a list of items to another list by applying a function to each of the items in the original list. Since Bits
is a list of Bit
s, and String
is a list of Char
s, we can thus map each Bit
to a Char
to obtain a String
of '0'
s and '1'
s for the Zero
and One
s respectively.
Upvotes: 2