繁体   English   中英

“Eta reduce”并不总是在Haskell中举行?

[英]"Eta reduce" is not always held in Haskell?

我发现我可以说

{-# LANGUAGE RankNTypes #-}
f1 :: (forall b.b -> b) -> (forall c.c -> c)
f1 f = id f

(并且 HLint 告诉我我可以在这里做“Eta reduce”),但是

f2 :: (forall b.b -> b) -> (forall c.c -> c)
f2 = id

编译失败:

Couldn't match expected type `c -> c'
            with actual type `forall b. b -> b'
Expected type: (forall b. b -> b) -> c -> c
  Actual type: (forall b. b -> b) -> forall b. b -> b
In the expression: id
In an equation for `f2': f2 = id

实际上我在更复杂的情况下也有类似的问题,但这是我能想到的最简单的例子。 因此,要么 HLint 无法在此处提供适当的建议,要么编译器应检测到这种情况,是吗?

更新

另一个令人着迷的问题看起来很相似。 然而,尽管这两个答案都非常有用,但都不让我满意,因为它们似乎没有触及问题的核心。

例如,我什至不允许为建议的 rank 2 类型分配id

f2 :: (forall b.b -> b) -> (forall c.c -> c)
f2 = id :: (forall b.b -> b) -> (forall c.c -> c)

如果问题仅与类型推断有关,则应使用显式类型符号来解决它(id 具有类型a -> a ,并且它已被约束为(forall bb -> b) -> (forall cc -> c) 。因此证明这种使用是合理的, (forall bb -> b)必须匹配(forall cc -> c) ,这是真的)。 但上面的例子表明情况并非如此。 因此,这是“eta reduce”的真正例外:您必须向双方显式添加参数才能将等级 1 类型的值转换为等级 2 类型的值。

但是为什么会有这样的限制呢? 为什么计算机不能自动统一等级 1 类型和等级 2 类型(忘记类型推断,所有类型都可以通过符号给出)?

我不确定 HLint 是否知道RankNTypes ,也许不知道。

事实上,在扩展的情况下,eta 减少通常是不可能的。 GHC 不能只是统一a->a(forall bb -> b) -> (forall cc -> c) ,否则它会完全搞乱它对 Rank1-code 1 的类型推断能力。 OTOH,将(forall bb -> b)a参数统一起来不是问题; 结果被确认为(forall bb -> b)(forall cc -> c)匹配。


1考虑map id [(+1), (*2)] 如果允许id具有您正在处理的类型,编译器最终可能会为多态Num函数生成不同的实例选择,这当然是不可能的。 还是应该? 我不确定,仔细想想……

无论如何,我很确定它证明了使用 RankNTypes,完全类型推断是不可能的,因此至少要在 Rank1 子集中获得它,GHC 通常必须默认将此作为不太可能的多态性选择。

暂无
暂无

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

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