我有一个代数数据类型,其中一些构造函数具有可比较的值,而一些构造函数则没有。我编写了一些比较函数,它们的工作方式类似于标准(==)
和(/=)
运算符,但返回Nothing
用于没有意义的比较:
data Variant = IntValue Int
| FloatValue Float
| NoValue
equal :: Variant -> Variant -> Maybe Bool
equal (IntValue a) (IntValue b) = Just (a == b)
equal (FloatValue a) (FloatValue b) = Just (a == b)
equal _ _ = Nothing
unequal :: Variant -> Variant -> Maybe Bool
unequal (IntValue a) (IntValue b) = Just (a /= b)
unequal (FloatValue a) (FloatValue b) = Just (a /= b)
unequal _ _ = Nothing
这行得通,但重复很笨拙——尤其是因为我实际上有更多的Variant
构造函数和更多的比较函数。
我想我可以将重复因素分解为一个在比较函数上参数化的辅助函数:
helper :: (Eq a) => (a -> a -> Bool) -> Variant -> Variant -> Maybe Bool
helper f (IntValue a) (IntValue b) = Just (f a b)
helper f (FloatValue a) (FloatValue b) = Just (f a b)
helper _ _ _ = Nothing
equal' :: Variant -> Variant -> Maybe Bool
equal' = helper (==)
unequal' :: Variant -> Variant -> Maybe Bool
unequal' = helper (/=)
但这不起作用,因为类型变量a
显然不能同时绑定到Int
;Float
的定义中helper
。GHC 将其绑定到Float
,然后在处理IntValue
.
直接使用时, like 函数(==)
是多态的;有没有办法将它传递给另一个函数并让它保持多态?