gpt4 book ai didi

haskell - 为什么默认情况下 forall(RankNTypes 用法)不适用?

转载 作者:行者123 更新时间:2023-12-02 09:57:11 25 4
gpt4 key购买 nike

我不太熟悉forall,但最近读到了这个问题:What does the `forall` keyword in Haskell/GHC do?

其中一个答案是这个例子:

 {-# LANGUAGE RankNTypes #-}
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)

解释很好,我明白 forall 在这里做什么。但我想知道,是否有特殊原因导致这不是默认行为。是否有过不利的时候?

编辑:我的意思是,默认情况下无法插入 forall 是否有原因?

最佳答案

嗯,它不是 Haskell 2010 标准的一部分,因此默认情况下不会启用它,而是作为语言扩展提供。至于为什么它不在标准中,n 级类型比 Haskell 标准的普通 1 级类型更难实现;它们也并不那么频繁地被需要,因此出于语言和实现简单性的原因,委员会可能决定不打扰它们。

当然,这并不意味着 n 级类型没有用处;它们确实如此,没有它们,我们就不会有像 ST monad 这样有值(value)的工具。 (它提供了高效的本地可变状态 - 就像 IO 一样,您所能做的就是使用 IORef)。但它们确实给语言增加了相当多的复杂性,并且在应用看似良性的代码转换时可能会导致奇怪的行为。例如,一些 n 级类型检查器将允许 runST (do { ... }) 但拒绝 runST $ do { ... },即使这两个表达式在没有 n 阶类型的情况下总是等价的。请参阅this SO question有关它可能导致的意外(有时甚至是烦人)行为的示例。

如果像 sepp2k 所问的那样,您反而会问为什么必须将 forall 显式添加到类型签名中以获得更高的通用性,那么问题就在于 (forall x.x -> f x) -> (a, b) -> (f a, f b) 实际上是比 (x -> f x) -> (a, b) -> (f a, f b) 限制性更强的类型)。对于后者,您可以传入 x -> f x 形式的任何函数(对于任何 fx),但对于前者,您传入的函数必须适用于all x。因此,例如,String -> IO String 类型的函数将是第二个函数的允许参数,但不是第一个函数;它必须具有 a -> IO a 类型。如果后者自动转化为前者,那就太困惑了!他们是两种截然不同的类型。

将隐式的 forall 显式化可能更有意义:

forall f x a b. (x -> f x)           -> (a, b) -> (f a, f b)
forall f a b. (forall x. x -> f x) -> (a, b) -> (f a, f b)

关于haskell - 为什么默认情况下 forall(RankNTypes 用法)不适用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10129101/

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