gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 14:55:49 24 4
gpt4 key购买 nike

我有一个代数数据类型,其中一些构造函数具有可比较的值,而一些构造函数则没有。我写了一些比较函数,其工作方式类似于标准 (==)(/=)运算符,但返回 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com