映射到 RankNTypes 函数

mapping over RankNTypes functions

使用 中的 rankN

{-# LANGUAGE RankNTypes #-}
rankN :: (forall n. Num n => n -> n) -> (Int, Double)
rankN f = (f 1, f 1.0)

为什么做不到map rankN [negate]?有什么方法可以实现吗?

我想我现在(大部分)理解了 RankNTypes,并且看到我可以做到 rankN (+1)rankN negate

(为什么 map rankN [negate] 给出了一个奇怪的错误 Couldn't match type ‘n’ with ‘Integer’,而我认为不涉及任何 Integer?)

此外,我刚刚查看了 :t map rankN。它给出了可怕的 Couldn't match type ‘a’ with ‘n -> n’ because type variable ‘n’ would escape its scope. This (rigid, skolem) type variable is bound by...。我知道在某些情况下该错误是如何产生的,但不太明白为什么它会适用于此处。

谢谢,抱歉,如果这是一个骗局。 (但我无法在所有其他 RankNTypes 问题中找到答案。)

默认情况下不起作用的原因是因为映射的类型是(a -> b) -> [a] -> [b],但在这种情况下,您不能将a实例化为涉及forall的类型forall n. Num n => n -> n。这种实例化被称为 impredicative,GHC 很长一段时间都没有(可靠地)支持它。

自 GHC 9.2.1 以来,ImpredicativeTypes 扩展有一个新的可靠实现,它允许您强制实例化:

GHCi, version 9.2.0.20210821: https://www.haskell.org/ghc/  :? for help
ghci> :set -XImpredicativeTypes
ghci> :t rankN
rankN :: (forall n. Num n => n -> n) -> (Int, Double)
ghci> :t map rankN 
map rankN :: [forall n. Num n => n -> n] -> [(Int, Double)]
ghci> :t map rankN [negate]
map rankN [negate] :: [(Int, Double)]
ghci> map rankN [negate]
[(-1,-1.0)]