我是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'匹配
这是合理的,但是当我替换a为BoolI时也会出错.我怎样才能使它在首位的工作,我可以限制类型a和b-例如,如果我想要的东西a永远是Bool和b永远是()?
你写,你写了一个元组的情况下(a, b),元组是Printable在案件中的项目a和b有Printable.但是,这并不意味着a或b有BoolS,或单位.
您可能认为 - 就像在许多语言中一样 - (==)运算符可以处理任何两种类型,但在Haskell中(==)有类型(==) :: Eq a => a -> a -> Bool,因此它是左右操作数具有相同类型的函数.所以我们不能使用x == True,除非x是Bool.
我们不需要这些警卫.我们需要做的是调用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 == True和x == False,但我建议你不要这样做,因为这违反了DRY原则:d on't [R EPEAT ÿ我们自己.