繁体   English   中英

类型统一/函数应用程序如何在 Haskell 的高层次上工作?

[英]How does type unification/function application work at a high level in Haskell?

我觉得我并没有真正了解函数应用程序是如何工作的,或者我可能正在关注一些我不应该做的事情。

让我们尝试确定(fmap .)的类型签名

fmap :: (x -> y) -> fx -> fy

(.) :: (b -> c) -> (a -> b) -> a -> c -- signatures taken from GHC

fmap应用于(.) ,我们本质上想让(x -> y) -> fx -> fy(b -> c)相等。 当我第一次尝试这样做时,我记得有一段非常艰难的时光。 您必须将一组 4 个变量与一组 2 个变量相匹配,所以显然您必须进行一些分组,但是如何? 我看到了 3 种可能的解决方案,它们都有效吗? 还是只有1? 我读到编译器并没有真正考虑括号,所以我们最终得到x -> y -> fx -> fyb -> c ,还有与右边相关的函数,所以fmap实际上应该看起来像x -> (y -> (fx -> fy)) ,这导致我

b = x

c = y -> fx -> fy

导致(a -> x) -> (a -> y -> fx -> fy)作为(fmap .)的签名。

我已经看到解决这个问题的分组是(a -> b) -> (fa -> fb) 所以

b = x -> y

c = fx -> fy

导致(a -> x -> y) -> a -> fx -> fy ,这与 GHC 的(a1 -> a2 -> b) -> a1 -> f a2 -> fb if 或多或少相同你重命名一些类型变量。

现在比较两个结果,去掉括号:

a -> x -> a -> y -> fx -> fy

a -> x -> y -> a -> fx -> fy

我们可以清楚地看到第 3 和第 4 个参数类型是切换的,这意味着它们显然不一样,因为flip是一个东西。 这意味着这个替换

b = x

c = y -> fx -> fy

无效。 还是我错过了什么?

我有一种感觉,当我应该反过来做时,我正试图根据签名使函数工作。 :t fmap 'c'失败, Couldn't match expected type 'a -> b' with actual type 'Char'这意味着您不能真正部分应用fmapa -> b部分。 您只能部分应用fmap本身,我猜它的第一个参数是不可分割的。 我不知道我是否得到了这一切背后的模式。

我真的应该尝试编写一个类型化的 lambda 演算。

我看到了 3 种可能的解决方案,它们都有效吗?

不。

还是只有1?

只有一个。 (x -> y) -> fx -> fy等于(x -> y) -> (fx -> fy)并且仅是因为->是右结合的。 把括号放在其他点是错误的。

我读到编译器并没有真正考虑括号,

那是假的。 编译器隐含地工作,因为括号总是以右关联方式添加:类型a -> b -> c -> d仅作为a -> (b -> (c -> d))处理。 相比之下,类型(a -> b) -> c -> d仅被处理为(a -> b) -> (c -> d) ,类型(a -> b -> c) -> d仅作为(a -> (b -> c)) -> d处理。

所以我们最终得到x -> y -> fx -> fyb -> c

不,那是错误的,你必须保留括号。 我们必须满足类型相等

(x -> y) -> (f x -> f y)
~
b -> c

唯一的解决方案是

b ~ (x -> y)
c ~ (f x -> f y)

正如你后来发现的那样。

要了解统一中发生了什么,我认为如果您从以右关联方式添加隐式括号开始是有益的。 如果你这样做,你可以忘记像a -> b -> c这样的类型,而只关心基本情况(T -> U)及其统一步骤:

from (T1 -> U1) ~ (T2 -> U2)
deduce T1 ~ T2 and U1 ~ U2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM