两个变量的类实例

Emb*_*ler 2 haskell

我是Haskell的新手并且创建了这个类

class Printable a where 
    toString :: a -> String
Run Code Online (Sandbox Code Playgroud)

还有两个例子

instance Printable Bool where
    toString x | x == True = "true"
               | x == False  = "false" 

instance Printable () where
    toString x = "unit type"
Run Code Online (Sandbox Code Playgroud)

它们工作得很好,现在我想创建一个带有两个参数的实例,但是我遇到了麻烦.到目前为止我创造的是

instance (Printable a, Printable b) => Printable (a, b) where
    toString x | fst x == True = "(true,unit type)"
Run Code Online (Sandbox Code Playgroud)

但现在我得到了错误

无法将预期类型'a'与实际类型'Bool'匹配

这是合理的,但是当我替换aBoolI时也会出错.我怎样才能使它在首位的工作,我可以限制类型ab-例如,如果我想要的东西a永远是Boolb永远是()?

Wil*_*sem 8

你写,你写了一个元组的情况下(a, b),元组是Printable在案件中的项目abPrintable.但是,这并不意味着abBoolS,或单位.

您可能认为 - 就像在许多语言中一样 - (==)运算符可以处理任何两种类型,但在Haskell中(==)有类型(==) :: Eq a => a -> a -> Bool,因此它是左右操作数具有相同类型的函数.所以我们不能使用x == True,除非xBool.

我们不需要这些警卫.我们需要做的是调用toString操作数的函数,所以:

instance (Printable a, Printable b) => Printable (a, b) where
    toString (x,y) = "(" ++ toString x ++ "," ++ toString y ++ ")"
Run Code Online (Sandbox Code Playgroud)

我们也可以替换[x] ++,x : ...所以我们可以将其重写为:

instance (Printable a, Printable b) => Printable (a, b) where
    toString (x,y) = '(' :  toString x ++ ',' : toString y ++ ")"
Run Code Online (Sandbox Code Playgroud)

编辑:如果你想a永远是一个Bool,你可以写:

instance Printable b => Printable (Bool, b) where
    toString (x,y) = '(' :  toString x ++ ',' : toString y ++ ")"
Run Code Online (Sandbox Code Playgroud)

当然,你可以现在添加卫士,模式匹配,或一些其他方法来区分x == Truex == False,但我建议你不要这样做,因为这违反了DRY原则:d on't [R EPEAT ÿ我们自己.