我现在正在学习Haskell并尝试将我的数据(类似于Maybe)作为Eq
的实例,如下所示。
module Main where
data MyMaybe a = MyNothing | MyJust a
instance (Eq a) => Eq (MyMaybe a) where
MyNothing == MyNothing = True
MyJust x == MyJust y = x == y
_ == _ = False
main :: IO ()
main = do
let b0 = MyJust 42 == MyJust 42 -- OK
print b0 -- True
let b1 = MyNothing == MyNothing -- Build error!
print b1
但是编译器在行let b1 = MyNothing == MyNothing
中返回错误,如下所示。
?暧昧类型变量“A0”从使用所产生的“==” 防止约束“(等式A0)”被解决。 可能的解决办法:使用类型注释,以指定“A0”应该是。 这些潜在的情况下存在: 实例等式订购 - 在“GHC.Classes”定义
...
我该如何解决?
...我搜索了现有的问题和答案。下面的内容似乎与我的相近,但我认为我的代码已经解决了答案中提出的要点。
答案 0 :(得分:2)
问题是MyMaybe
是参数化类型,但在表达式MyNothing == MyNothing
中,编译器无法确定您是否需要MyMaybe Int
,MyMaybe String
,{ {1}},或其他。
您可以使用类似的类型注释来帮助它:
MyMaybe (Int -> Bool)
答案 1 :(得分:2)
问题在于MyNothing
的{{1}}类型对MyMaybe a
的限制没有限制。
当您编写a
时,MyNothing == MyNothing
的类型将两个(==) :: (Eq b) => b -> b -> Bool
限制为具有相同的类型(编译器最初以MyNothing
和{{1开头但是,然后意识到MyNothing :: MyMaybe a0
)。
但要解决MyNothing :: MyMaybe a1
本身,编译器需要找到正确的a0 == a1
实例(因为那里定义了==
)。我们的类型是Eq
,这很好:我们在那里有一个==
实例。但它还需要一个MyMaybe a
实例,由于我们不知道Eq (MyMaybe a)
是什么,因此无法解决。 (在Eq a
情况下a
实际上没有使用并不重要;类型检查不会注意运行时值。)
这是编译器放弃的地方,说它无法解析约束(Eq a)
,因为类型变量MyNothing == MyNothing
不明确。
解决这个问题很简单。只需给编译器一个提示应该使用哪种类型:
(Eq a0)
或者:
a0
实际类型并不重要(只要它有一个let b1 = MyNothing == (MyNothing :: MyMaybe Integer) -- for example
实例)。
这种歧义并不仅限于您的let b1 = MyNothing == (MyNothing :: MyMaybe (Double, [String]))
类型。您应该使用Eq
(MyMaybe
)或Maybe
(Nothing == Nothing
)获得相同的错误。在所有情况下都涉及多态常量([]
,[] == []
)。
您的示例实际上在ghci中有效。这是因为ghci使用extended defaulting rules并最终将Nothing :: Maybe a
转换为[] :: [a]
;即比较以a
完成。