Class Can';t使String成为Haskell中类的实例
我在玩弄哈斯克尔的课程。 我写了几行愚蠢的代码来掌握诀窍。我编写了一个名为Class Can';t使String成为Haskell中类的实例,class,haskell,Class,Haskell,我在玩弄哈斯克尔的课程。 我写了几行愚蠢的代码来掌握诀窍。我编写了一个名为Slang的类,它只有一个函数。当我将Integer作为类的实例时,它工作得很好。但当我将String作为类的实例时,它不会编译。我一直在根据错误输出告诉我的内容来摆弄程序,但没有用。我知道它为什么会起作用 以下是错误后的代码: module Practice where class Slang s where slangify :: s -> String instance Slang Integer
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"
错误:
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>
问题是字符串不是整数那样的基类型。你想做的实际上是
instance Slang [Char] where
slangify str = "bro"
然而,Haskell 98禁止这种类型的typeclass,以保持简单,并使人们更难编写像这样的重叠实例
instance Slang [a] where
-- Strings would also fit this definition.
slangify list = "some list"
无论如何,正如错误消息所示,您可以通过启用扩展来绕过此限制。我在Haskell文献(也称为我当前的圣经)中做了一些研究,并找到了一个有效解决我的问题的示例 基本上,在这个解决方法中,您将
Char
设置为类的实例(在本书的示例中,它被称为Visible
),然后您可以将[chars]
aka字符串设置为类的实例,并且只需规定类型变量chars
是“Visible”的实例。
查看下面的代码更容易理解:
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
我的GHCi加载和函数调用:
*Practice> :l Practice
[1 of 1] Compiling Practice ( Practice.hs, interpreted )
Ok, modules loaded: Practice.
*Practice> size "I love Stack!"
14
*Practice>
尤里卡 我写的一篇老博文的无耻插件,探讨了前奏如何绕过这个限制。如何启用FlexibleInstances?@lmay:启用扩展的最简单方法是添加一条注释,如
{-#LANGUAGE FlexibleInstances}
到Haskell文件的顶部。还应该注意的是,使用Data.Text
,这是一种基本类型,可以在没有任何扩展名的情况下声明实例,而不是String
。这很聪明,但我认为只有在此类的唯一实例为Char的情况下才有效。如果使用任何其他类型创建实例,则在Visible[a]实例中使用的特定于字符串的函数将不起作用。直到我发布该评论后,我才意识到该线程来自2013年:)