Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

haskell - Why can I not make String an instance of a typeclass?

Given:

data Foo =
  FooString String
  …

class Fooable a where --(is this a good way to name this?)
  toFoo :: a -> Foo

I want to make String an instance of Fooable:

instance Fooable String where
  toFoo = FooString

GHC then complains:

Illegal instance declaration for `Fooable 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 `Fooable String'

If instead I use [Char]:

instance Fooable [Char] where
  toFoo = FooString

GHC complains:

Illegal instance declaration for `Fooable [Char]'
   (All instance types must be of the form (T a1 ... an)
    where a1 ... an are type *variables*,
    and each type variable appears at most once in the instance head.
    Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Fooable [Char]'

Question:

  • Why can I not make String and instance of a typeclass?
  • GHC seems willing to let me get away with this if I add an extra flag. Is this a good idea?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is because String is just a type alias for [Char], which is just the application of the type constructor [] on the type Char, so this would be of the form ([] Char). which is not of the form (T a1 .. an) because Char is not a type variable.

The reason for this restriction is to prevent overlapping instances. For example, let's say you had an instance Fooable [Char], and then someone later came along and defined an instance Fooable [a]. Now the compiler won't be able to figure out which one you wanted to use, and will give you an error.

By using -XFlexibleInstances, you're basically promising to the compiler that you won't define any such instances.

Depending on what you're trying to accomplish, it might be better to define a wrapper:

newtype Wrapper = Wrapper String
instance Fooable Wrapper where
    ...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...