Reputation: 23322
I'm playing around trying to understand classes in Haskell.
I wrote a silly few lines of code to get the hang of it. I wrote a class called Slang
that has one function. When I make Integer an instance of my class, it works fine. But when I make String an instance of my class it won't compile. I've been fidgeting with the program based on what the error output tells me but to no avail. I have idea why it work...
Here is the code followed by the error:
module Practice where
class Slang s where
slangify :: s -> String
instance Slang Integer where
slangify int = "yo"
instance Slang String where -- When I take this segment out, it works fine
slangify str = "bro"
ERROR:
Prelude> :load Practice
[1 of 1] Compiling Practice ( Practice.hs, interpreted )
Practice.hs:9:10:
Illegal instance declaration for `Slang String'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Slang String'
Failed, modules loaded: none.
Prelude>
Upvotes: 9
Views: 846
Reputation: 23322
I did some research in my Haskell literature (aka my current Bible) and found an example that effectively solves my problem.
Basically, in this workaround you set Char
to be an instance of the class (in the book's example it's called Visible
) and then you can set [chars]
aka a String, to be an instance of the class as well ONLY WITH the stipulation that the type variable chars
be an instance of `Visible'.
It's easier to understand if you look at the code below:
module Practice where
class Visible a where
toString :: a -> String
size :: a -> Int
instance Visible Char where
toString ch = [ch]
size _ = 1
instance Visible a => Visible [a] where
toString = concat . map toString
size = foldr (+) 1 . map size
My GHCi load and function call:
*Practice> :l Practice
[1 of 1] Compiling Practice ( Practice.hs, interpreted )
Ok, modules loaded: Practice.
*Practice> size "I love Stack!"
14
*Practice>
Eureka!
Upvotes: 5
Reputation: 69944
The problem is that String is not a base type like Integer. What you are trying to do is actually
instance Slang [Char] where
slangify str = "bro"
However, Haskell98 forbids this type of typeclass in order to keep things simple and to make it harder for people to write overlapping instances like
instance Slang [a] where
-- Strings would also fit this definition.
slangify list = "some list"
Anyway, as the error message suggests, you can get around this restriction by enabling the FlexibleInstances extension.
Upvotes: 14