11

Haskell 中的可变向量具有三个元素级别的修改器:

read :: PrimMonad m => MVector (PrimState m) a -> Int -> m a
write :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m ()
swap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m ()

现在我可以很好地使用这些——

import Data.Vector
import Data.Vector.Mutable 
import Control.Monad.ST
import Control.Monad.Primitive 

incrAt :: Vector Double -> Int -> Vector Double
incrAt vec i = runST $ do
  mvec <- thaw vec
  oldval <- read mvec i
  write mvec i (oldval + 1)
  freeze mvec

但是这里发生了什么?什么是PrimMonad? 并且是PrimState构造函数?

我知道这里有一些绑定,在一个PrimMonad类单子上。thaw返回m (MVector (PrimState m) a)ma在哪里PrimMonad...但是 monad 包含自己?为什么m在另一个上下文中m

我看到一切基本上都绑定在 this PrimStateor上PrimMonad,但我不明白这与可变/可存储向量有什么关系。那些允许它们存储状态的类型类有什么特别之处吗?

感谢您的时间!

4

1 回答 1

16

我认为您正在使用矢量包,如

import Data.Vector.Mutable

遵循PrimMonad类型类会导致低级细节;需要注意的是两个实例:

instance PrimMonad IO where ...
instance PrimMonad (ST s) where ...

所以(PrimMonad m)只是一种说法m,要么是IO要么(ST s)。这是 Haskell 设置的两个基本 monad,可以让你改变内存。需要明确的是,m是一个类型构造函数,并且应用于m一个类型,比如Int给出一个类型:m Int

强调:IO并且(ST s)是特殊的,因为它们允许您使用这种能力来“存储状态”来改变实际内存。他们以 Haskell 的其余部分隐藏的原始形式公开了此功能。

现在 PrimState 是一个新事物:关联的数据类型。在PrimMonad类型类中有一个声明:

-- | Class of primitive state-transformer monads
class Monad m => PrimMonad m where
  -- | State token type
  type PrimState m

代码中的类型(PrimState m)取决于(PrimMonad m)分配给它的实例。

instance PrimMonad IO where
  type PrimState IO = RealWorld

instance PrimMonad (ST s) where
  type PrimState (ST s) = s

类型是 GHC 中 IO的RealWorld低级内部实现细节。s附加的类型(ST s)是存在类型技巧,它可以runST证明没有任何可变的东西可以逃脱(ST s)单子。

为了使相同的代码在其中工作,类型IO类(带有关联的)用于提供临时重载。(ST s)PrimMonadPrimState

于 2013-06-29T09:46:18.020 回答