Data.Vector具有以下功能:
modify :: (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
是否可以创建一个函数,例如:
modify :: [(forall s. MVector s a -> ST s ())] -> Vector a -> Vector a
我已经尝试了
{-# LANGUAGE RankNTypes, ImpredicativeTypes #-}
import qualified Data.Vector.Mutable as MV
import qualified Data.Vector as V
import Control.Monad.ST
import Control.Monad.Primitive
unsafeModify :: [(forall s . MV.MVector s Int -> ST s ())] -> V.Vector Int -> V.Vector Int
unsafeModify mods vec = runST $ do
mvec <- V.unsafeThaw vec
sequence_ (map ($ mvec) mods)
V.unsafeFreeze mvec
但是我收到了错误
Muts.hs:11:28:
Couldn't match type ‘forall s1. V.MVector s1 Int -> ST s1 ()’
with ‘V.MVector s Int -> ST s a0’
Expected type: [V.MVector s Int -> ST s a0]
Actual type: [forall s. V.MVector s Int -> ST s ()]
Relevant bindings include
mvec :: V.MVector s Int (bound at Muts.hs:10:5)
In the second argument of ‘map’, namely ‘mods’
In the first argument of ‘sequence’, namely ‘(map ($ mvec) mods)’
答案 0 :(得分:3)
通常的技巧是收拾你的功能,因此:
data Box a = Box { unBox :: forall s. MVector s a -> ST s () }
modifyAll :: [Box a] -> Vector a -> Vector a
modifyAll fs = modify (\mvector -> mapM_ (\b -> unBox b mvector) fs)
答案 1 :(得分:3)
更改unsafeModify
的类型。特别是,将forall s.
浮动到列表之外。您希望所有函数共享相同的状态标记(由runST
确定),因此您不需要让每个函数都使用另一个 s
:
{-# LANGUAGE RankNTypes #-}
import qualified Data.Vector.Mutable as MV
import qualified Data.Vector as V
import Control.Monad (mapM_)
import Control.Monad.ST
import Control.Monad.Primitive
unsafeModify :: (forall s . [MV.MVector s Int -> ST s ()]) -> V.Vector Int -> V.Vector Int
unsafeModify mods vec = runST $ do
mvec <- V.unsafeThaw vec
mapM_ ($ mvec) mods
V.unsafeFreeze mvec
答案 2 :(得分:1)
这对我有用:
==>cscript //NOLOGO D:\VB_scripts\SO\32416311.vbs
45 0000000000101101 00000000000000000000000000101101
-45 1111111111010011 11111111111111111111111111010011
==>
答案 3 :(得分:1)
当进行类型检查时,GHC只会实例化具有单形类型的类型变量。自map :: (a -> b) -> [a] -> [b]
起,这已经排除了您的预期用法,因为a
必须实例化为forall s. MVector s a -> ST s ()
,而这种情况不可能发生。这是ImpredicativeTypes
几乎不可用于GHC的一个原因。
由于我们不能使用通常的高阶流控制函数,我们必须写出一个显式的递归函数:
{-# LANGUAGE ScopedTypeVariables #-}
unsafeModify :: [(forall s . MV.MVector s Int -> ST s ())] -> V.Vector Int -> V.Vector Int
unsafeModify mods vec = runST $ do
(mvec :: MV.MVector s Int) <- V.unsafeThaw vec
let go :: [(forall s . MV.MVector s Int -> ST s ())] -> ST s (V.Vector Int)
go [] = V.unsafeFreeze mvec
go (mod:mods) = do
mod mvec
go mods
go mods
ScopedTypeVariables
也是必要的,因为我们希望s
的返回类型中的go
与我们绑定s
的{{1}}相同。