映射到 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)]
使用 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)]