haskell - 高阶函数内的多态性?

标签 haskell types polymorphism higher-order-functions

我有一个代数数据类型,其中一些构造函数具有可比较的值,而一些构造函数则没有。我写了一些比较函数,其工作方式类似于标准 (==)(/=)运算符,但返回 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显然不能同时绑定(bind)IntFloat同时在helper的定义中; GHC 将其绑定(bind)到 Float然后提示处理 IntValue 的行上的类型不匹配.

(==) 这样的函数直接使用时是多态的;有没有办法将它传递给另一个函数并让它保持多态?

最佳答案

是的,这是可能的,但仅限于 language extensions :

{-# LANGUAGE Rank2Types #-}

helper :: (forall a. (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
forall a.听起来像什么; a在括号内被普遍量化,在括号外超出范围。这意味着 f参数必须对所有类型 a 作为 Eq 的实例都是多态的,这正是你想要的。

此处的扩展称为“等级 2”,因为它允许在最外层范围内使用常规样式的多态,以及此处示例中的多态参数。要进一步嵌套,您需要扩展 RankNTypes ,这是相当自我描述的。

顺便说一句,关于更高级别的多态类型——请记住 forall是将变量实际绑定(bind)到类型的内容;事实上,你可以认为它们的行为很像 lambda。当你将这样的函数应用到具有具体类型的东西上时,参数的类型会被 forall 隐式绑定(bind)。为那个用途。例如,如果您尝试使用其类型被内部 forall 绑定(bind)的值,就会出现这种情况。在该功能之外;该值的类型已经超出范围,这使得做任何明智的事情变得困难(正如您可能想象的那样)。

关于haskell - 高阶函数内的多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7061538/

相关文章:

Haskell:从元组类型中检索第n个值

types - 类型的基数

MySQL 截断 GROUP_CONCAT 函数的连接结果

c - C 中的类型有任何保证的最小尺寸吗?

java - java 难道不应该将重载函数与大多数特定类型相匹配吗?

inheritance - 如何使用继承来建模 RESTful API?

c++ - 我可以使用模板作为多态处理数组的安全解决方案吗?

haskell - 如何减去 Haskell 中的 Maybe 值?例如,如果我想减去 Just 8 - Just 5 得到 Just 3,我该怎么做?

haskell - 如何从类型表示中获取 Data.Data.Constr 等?

haskell - 在 Haskell 中读取大型二进制文件的最快方法是什么?