Haskell 如何打印可变向量

Haskell how to print mutable vector

提问人:daydaynatation 提问时间:4/1/2021 最后编辑:Will Nessdaydaynatation 更新时间:4/1/2021 访问量:251

问:

import           Control.Monad.IO.Class  (liftIO)
import           Control.Monad.Primitive
import qualified Data.Vector             as V
import qualified Data.Vector.Mutable     as MV

fromList :: [a] -> IO (MV.IOVector a)
fromList = V.thaw . V.fromList

printMV :: PrimMonad m => MV.MVector (PrimState m) a -> m ()
printMV = liftIO . print . V.freeze

我想打印(很惊讶没有显示实例)。所以我必须首先. 然后我遇到了类型错误:MVectorfreezVector

Algo/QuickSort.hs:12:11: error: …
    • Couldn't match type ‘PrimState m’ with ‘PrimState m0’
      Expected type: MV.MVector (PrimState m) a -> m ()
        Actual type: MV.MVector (PrimState m0) a -> m ()
      NB: ‘PrimState’ is a non-injective type family
      The type variable ‘m0’ is ambiguous
    • In the expression: liftIO . print . V.freeze
      In an equation for ‘printMV’: printMV = liftIO . print . V.freeze
    • Relevant bindings include
        printMV :: MV.MVector (PrimState m) a -> m ()
          (bound at /home/skell/btree/Algo/QuickSort.hs:12:1)
   |
Compilation failed.

我也试过IOVector

printMV :: MV.IOVector a -> IO ()
printMV = liftIO . print . V.freeze

这次的错误不同:

Algo/QuickSort.hs:12:28: error: …
    • Couldn't match type ‘PrimState m0’ with ‘RealWorld’
      Expected type: MV.IOVector a -> m0 (V.Vector a)
        Actual type: MV.MVector (PrimState m0) a -> m0 (V.Vector a)
      The type variable ‘m0’ is ambiguous
    • In the second argument of ‘(.)’, namely ‘V.freeze’
      In the second argument of ‘(.)’, namely ‘print . V.freeze’
      In the expression: liftIO . print . V.freeze
   |
Compilation failed.
哈斯克尔 向量 印刷 可变

评论

1赞 Daniel Wagner 4/1/2021
不可能有一个实例(或者至少,不可能是你可能想到的实例),因为不允许这样做,并且需要从向量中读取。ShowShowshowIOIO
0赞 daydaynatation 4/1/2021
@DanielWagner 所以你的意思是所有 Haskellers 都像我刚才所做的那样,为了打印 ?vector
1赞 Daniel Wagner 4/1/2021
嗯。好吧,这种说法可能太强烈了。ing绝对是一种方式;但还有很多其他的。例如,可以在不冻结的情况下迭代索引,或者以某种算法特定的顺序呈现元素,使其更易于人类阅读,或者将向量转换为树,因为它实际上是一个线性化堆,或者使用向量创建一个一元计算的块小部件,或者,或者,或者......freeze
0赞 daydaynatation 4/1/2021
@DanielWagner 你如何迭代一个?我找不到它的 or 实例。我可以以某种方式吗?MVectorFoldableTraversablemapM_ print
0赞 Daniel Wagner 4/1/2021
不可能有 或 实例,原因与不可能有实例的原因基本相同。但是,例如 适用于基于 的向量,其中 是 。(或者,如果您觉得需要速度,可以使用。如果高级 Haskeller 不信任列表融合来消除 .但是,只有在验证了这个循环的速度确实很重要之后,这两者都应该发生 - 当打印它几乎从不重要时。FoldableTraversableShowmapM_ (MV.read v >=> print) [0 .. MV.length v-1]IOMVData.Vector.MutableMV.unsafeRead[0 .. MV.length v-1]

答:

4赞 Random Dev 4/1/2021 #1

有几件事正在发生 - 第一个解决方案:

printMV :: MonadIO m => Show a => PrimMonad m => MV.MVector (PrimState m) a -> m ()
printMV v = do
    fv <- V.freeze v
    liftIO $ print fv

所以问题:

  • freeze本身就是一个 -action,所以它需要绑定m
  • liftIO需要实例MonadIO
  • 为了成为 - 也必须在那个班级Vector aShowa

您的第二个版本类似:

printMV2 :: Show a => MV.IOVector a -> IO ()
printMV2 v = V.freeze v >>= print
  • 需要实例Showa
  • 需要的结果(与上面相同 - 隐式地这样做)>>=V.freezedo
  • 这里没有必要,因为你已经在其中了liftIO