下面的代码不会被编译:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV
bad :: V.Vector Int
bad = id . V.create $ do
v <- MV.new 1
MV.set v 0
pure v
• Couldn't match type ‘m0 (MV.MVector (Control.Monad.Primitive.PrimState m0) a0)’ with ‘forall s. GHC.ST.ST s (MV.MVector s Int)’ Expected type: m0 (MV.MVector (Control.Monad.Primitive.PrimState m0) a0) -> V.Vector Int Actual type: (forall s. GHC.ST.ST s (MV.MVector s Int)) -> V.Vector Int • In the second argument of ‘(.)’, namely ‘V.create’ In the expression: id . V.create In the expression: id . V.create $ do { v <- MV.new 1; MV.set v 0; pure v }
但接下来会是:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as MV
good :: V.Vector Int
good = id <b>$</b> V.create $ do
v <- MV.new 1
MV.set v 0
pure v
stack
解析器是 lts-9.12
那么,如果我更喜欢按 (.)
组合,为什么会这样以及如何解决?
最佳答案
您已经明白了 GHC 无法执行谓词多态性这一事实。 V.create
具有更高等级的类型 forall a。拆箱 a => (forall s. ST s (MVector s a)) -> Vector a
,当你尝试将它应用到 (id .)::(x -> y) -> ( x -> y)
你最终需要实例化 x = forall s。 ST s (MVector s a)
,它爆炸了。这并不是说所需的实例化真的有什么错误;只是 GHC 无法处理它。曾经有一个扩展,ImpredicativePolymorphism
,它试图提供有限的支持,但从 GHC 8 开始,它已被完全破坏和弃用。 ($)
仍然有效的原因是因为它实际上是硬连接到 GHC 中的,这样它就可以避免这个问题,这就是为什么如果你试图定义
f $$ x = f x
并在这里使用它而不是 ($)
它会像 (id .)
一样失败。
关于haskell - 使用向量 `create` 函数组合任何函数时出现类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47239014/