我正在练习a tutorial on Haskell Vectors,作为练习,它要求您使用Data.Vector.Unboxed.modify
和“本教程前面介绍的功能”(即runST
和thaw
)重新实现freeze
。 >
这是我尝试过的:
#!/usr/bin/env stack -- stack --resolver lts-12.21 script import qualified Data.Vector.Unboxed as V import qualified Data.Vector.Unboxed.Mutable as VM -- import Data.Vector.Unboxed (modify) import Control.Monad.ST -- TODO: debug this... modify :: VM.Unbox a => (VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a modify sa v = runST $ do mv <- V.thaw v sa mv V.freeze mv main :: IO () main = do let vec = V.enumFromTo 1 10 :: V.Vector Int print $ modify (\v -> fmap (\_-> ()) $ VM.nextPermutation v) vec
哪个会出现编译错误:
$ ./modify.hs ./modify.hs:11:9: error: • Couldn't match type ‘s1’ with ‘s’ ‘s1’ is a rigid type variable bound by a type expected by the context: forall s1. ST s1 (V.Vector a) at /home/tom/code/fpco-haskell-tutorials/vector/modify.hs:(10,15)-(13,13) ‘s’ is a rigid type variable bound by the type signature for: modify :: forall a s. VM.Unbox a => (VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a at /home/tom/code/fpco-haskell-tutorials/vector/modify.hs:9:1-79 Expected type: ST s1 (VM.MVector s a) Actual type: ST s1 (VM.MVector (primitive-0.6.3.0:Control.Monad.Primitive.PrimState (ST s1)) a) • In a stmt of a 'do' block: mv <- V.thaw v In the second argument of ‘($)’, namely ‘do mv <- V.thaw v _ <- sa mv V.freeze mv’ In the expression: runST $ do mv <- V.thaw v _ <- sa mv V.freeze mv • Relevant bindings include sa :: VM.MVector s a -> ST s () (bound at /home/tom/code/fpco-haskell-tutorials/vector/modify.hs:10:8) modify :: (VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a (bound at /home/tom/code/fpco-haskell-tutorials/vector/modify.hs:10:1) | 11 | mv <- V.thaw v |
我认为重要的是:
Expected type: ST s1 (VM.MVector s a) Actual type: ST s1 (VM.MVector (primitive-0.6.3.0:Control.Monad.Primitive.PrimState (ST s1)) a)
看着我在
modify
的尝试:
modify :: VM.Unbox a => (VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a modify sa v = runST $ do mv <- V.thaw v sa mv V.freeze mv
我想表达的是:
Vector
解冻为MVector
Vector
如果我注释掉我尝试在哪里进行突变:
modify sa v = runST $ do mv <- V.thaw v -- sa mv V.freeze mv
代码编译并运行以生成未修改的向量。
$ ./modify.hs [1,2,3,4,5,6,7,8,9,10]
因此,我尝试应用有状态操作
sa
来修改可变向量mv
的方式出了点问题。
查看类型和the docs for thaw and freeze:
thaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a) freeze :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a) sa mv :: ST s ()
因此
do
块位于类型类m
的monadPrimMonad
中。
我以为ST s
会与之“对齐”以执行突变...
我尝试将其绑定到孔:
modify sa v = runST $ do mv <- V.thaw v _ <- sa mv V.freeze mv
但是那没什么不同,考虑到它,您不会期望它...
我认为这是有关monad变压器的一般问题。我需要在这里做些举重吗?
我需要做什么来用我的sa
进行可变载体的突变?
[我正在研究有关Haskell Vectors的教程,作为练习,它要求您使用runST和“我在教程中介绍的功能”重新实现Data.Vector.Unboxed.modify。]]]
只需更改类型签名:
modify :: VM.Unbox a => (forall s. VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a
-- ^^^^^^^^^