无法使String成为Haskell中类的实例

Cod*_*ein 9 haskell class

我正在试图理解Haskell中的类.我写了一些愚蠢的代码来获取它.我写了一个叫Slang有一个函数的类.当我将Integer作为我的类的一个实例时,它工作正常.但是当我将String作为我的类的一个实例时,它将无法编译.我一直在根据错误输出告诉我的程序而烦恼,但无济于事.我知道它为什么有用......

以下是错误后面的代码:

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"
Run Code Online (Sandbox Code Playgroud)

错误:

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>
Run Code Online (Sandbox Code Playgroud)

hug*_*omg 13

问题是String不是像Integer这样的基类型.你要做的实际上是

instance Slang [Char] where
    slangify str = "bro"
Run Code Online (Sandbox Code Playgroud)

但是,Haskell98禁止使用这种类型类型,以便简化操作并使人们更难以编写重叠的实例

instance Slang [a] where
    -- Strings would also fit this definition.
    slangify list = "some list"
Run Code Online (Sandbox Code Playgroud)

无论如何,正如错误消息所示,您可以通过启用FlexibleInstances扩展来绕过此限制.

  • 一篇旧博客文章的无耻插件我写了探索前奏如何解决这个限制[在Show](http://brandon.si/code/how-the-haskell-prelude-avoids-overlapping-types-in-show/ ). (3认同)
  • @lmay:启用扩展的最简单方法是在Haskell文件的顶部添加类似`{ - #LANGUAGE FlexibleInstances# - }`的注释. (3认同)
  • 还应该注意的是,最近使用`Data.Text`代替`String`,它是一个基类型,并且可以在没有任何扩展的情况下声明实例. (3认同)

Cod*_*ein 5

我在我的Haskell文献(也就是我现在的圣经)中做了一些研究,并找到了一个有效解决我问题的例子.

基本上,在这个变通方法中,你设置Char为类的一个实例(在本书的例子中它被调用Visible),然后你可以设置[chars]一个字符串,作为类的一个实例,只有类型变量chars是一个规定"可见"的例子.如果你看下面的代码,它会更容易理解:

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
Run Code Online (Sandbox Code Playgroud)

我的GHCi负载和函数调用:

*Practice> :l Practice
[1 of 1] Compiling Practice         ( Practice.hs, interpreted )
Ok, modules loaded: Practice.
*Practice> size "I love Stack!"
14
*Practice>
Run Code Online (Sandbox Code Playgroud)

找到了!