我如何解冻,变异,然后重新冻结Haskell向量?

问题描述 投票:0回答:1

我正在练习a tutorial on Haskell Vectors,作为练习,它要求您使用Data.Vector.Unboxed.modify和“本教程前面介绍的功能”(即runSTthaw)重新实现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的monad PrimMonad中。

我以为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。]]]

haskell monad-transformers haskell-vector
1个回答
0
投票

只需更改类型签名:

modify :: VM.Unbox a => (forall s. VM.MVector s a -> ST s ()) -> V.Vector a -> V.Vector a
--                       ^^^^^^^^^
© www.soinside.com 2019 - 2024. All rights reserved.