gpt4 book ai didi

haskell - 编写具有通用量化返回类型的函数

转载 作者:行者123 更新时间:2023-12-02 05:31:59 24 4
gpt4 key购买 nike

如果我写

foo :: (Num a) => a
foo = 42

GHC欣然接受,但如果我写

bar :: (Num a) => a
bar = (42 :: Int)

它告诉我预期类型 a 与推断类型 Int 不匹配。我不太明白为什么,因为 Inta 代表的类 Num 的一个实例。

我在尝试编写一个函数时遇到了同样的情况,该函数归结为问题的核心,大致如下所示:

-- Note, Frob is an instance of class Frobbable
getFrobbable :: (Frobbable a) => Frob -> a
getFrobbable x = x

这样的函数可以写吗?如何使结果与类型签名兼容?

最佳答案

您将类型类约束视为子类型约束。这是一件很常见的事情,但实际上它们只在逆变情况下重合,也就是说,当涉及函数参数而不是结果时.签名:

bar :: (Num a) => a

意味着 caller 可以选择 a 类型,前提是它是 Num 的实例。所以在这里,调用者可以选择调用 bar::Intbar::Double,它们应该都可以。所以 bar::(Num a) => a 必须能够构造任何种数字,bar 不知 Prop 体的类型是什么选择。

逆变情况完全相同,它只是符合 OO 程序员在这种情况下的直觉。例如。

baz :: (Num a) => a -> Bool

意味着 caller 可以一次又一次地选择类型 a baz 并不知道选择了什么特定类型。

如果您需要让被调用者选择结果类型,只需更改函数的签名以反射(reflect)此知识。例如:

bar :: Int

或者在您的 getFrobbable 案例中,getFrobbable::Frob -> Frob(这使得函数变得微不足道)。任何出现 (Frobbable a) 约束的地方,Frob 都会满足它,因此只需说 Frob 即可。

这可能看起来很尴尬,但实际上只是信息隐藏发生在函数式编程的不同边界。有一种方法可以隐藏具体的选择,但是不常见,我考虑一下a mistake在大多数情况下使用它。

关于haskell - 编写具有通用量化返回类型的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3306665/

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