【发布时间】:2020-05-14 16:36:18
【问题描述】:
我正在处理a tutorial on Haskell Vectors,作为练习,要求您使用runST 和“本教程前面介绍的功能”重新实现Data.Vector.Unboxed.modify,我认为它是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 块在类型类PrimMonad 中的monad m 内。
我的想法是ST s 会与它“对齐”以执行突变...
我尝试将它绑定到一个洞:
modify sa v = runST $ do
mv <- V.thaw v
_ <- sa mv
V.freeze mv
但这并没有什么不同,想想它,你不会期望它......
我认为这是关于 monad 转换器的一般问题。我需要在这里做一些提升吗?
我需要做什么来使用我的sa 执行可变向量的突变?
【问题讨论】:
标签: haskell monad-transformers haskell-vector