我正在完成一个关于 Haskell Vectors 的教程,作为练习,它要求你重新实现Data.Vector.Unboxed.modify
usingrunST
和“教程前面介绍的函数”,我认为它是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
。
查看类型以及thaw 和 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
块位于 typeclass 的 monadm
中PrimMonad
。
我的想法是,ST s
将与它“排队”以执行突变......
我尝试将其绑定到一个洞:
modify sa v = runST $ do
mv <- V.thaw v
_ <- sa mv
V.freeze mv
但这并没有什么不同,考虑到它,你不会期望它...
我认为这是关于 monad 转换器的一般问题。我需要在这里做一些提升吗?
那么我需要做什么来用我的来执行可变向量的突变sa
?