11

Haskell の可変ベクトルには、要素レベルのミューテーターが 3 つあります。

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)、どこmに a PrimMonad... がありますが、モナドはそれ自体を含んでいますか? m別のコンテキスト内にあるのはなぜmですか?

すべてが基本的に thisPrimStateまたはPrimMonadにバインドされていることがわかりますが、これが変更可能/保存可能なベクトルとどのように関係しているのかわかりません。状態を保存できる型クラスに何か特別なものはありますか?

お時間をいただきありがとうございます!

4

1 に答える 1

16

次のように、 vector packageを使用していると思います

import Data.Vector.Mutable

型クラスをたどると、PrimMonad低レベルの詳細につながります。注意すべきことは、次の 2 つのインスタンスです。

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

Soはどちらかまたは(PrimMonad m)の言い方です。これらは、メモリを変更できるように Haskell が設定されている 2 つの基本的なモナドです。明確にするために、は型コンストラクターであり、次のような型に適用するとtype: が得られます。mIO(ST s)mmIntm Int

強調すると、実際のメモリを変更するこの機能を使用して「状態を保存」できるため、IOandは特別です。(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

このRealWorld型は、GHC における IO の低レベルの内部実装の詳細です。s付加された型は、可変なものが何もモナドから逃れていないことを証明(ST s)できる、存在型のトリックです。runST(ST s)

で同じコードを機能させるにはIO(ST s)PrimMonadクラス (関連するPrimState) を使用してアドホック オーバーロードを提供します。

于 2013-06-29T09:46:18.020 に答える