2

ベクトル容量を超えたときに (命令型アルゴリズムの場合)STVector内で展開されるダイナミクスを作成しようとしています。ST monadそのために、 をラップする新しいデータ コンストラクターを作成し、最後に挿入されたベクターを追跡するためにSTVectorを追加しました。Int問題は、状態の実装が正しくないように見えるため、タイプチェッカーからエラーが発生することです。DVec s以下の例で状態を正しく管理する方法についての指針をいただければ幸いです。

{-# LANGUAGE BangPatterns #-}
module Test where
import Data.Vector.Unboxed.Mutable as MU
import Control.Monad.ST as ST
import Control.Monad.Primitive (PrimState)
import GHC.Float.RealFracMethods (int2Float)

type MVI1 s  = MVector (PrimState (ST s)) Int
data DVec s = DV {-# UNPACK #-}!Int -- this one keeps track of index of last vector
                                (MVI1 s)
append :: DVec s -> Int -> ST s (DVec s)
append (DV i v) x = do
   if i < MU.length v then MU.unsafeWrite v i x >> return $ DV (i+1) v
   else MU.unsafeGrow v (floor $ 1.5 * (int2Float $ MU.length v)) >>= (\y -> MU.unsafeWrite y i x >> return $ DV (i+1) y)

タイプチェッカーからのエラー:

Couldn't match type `s' with `PrimState ((->) (DVec s))'
  `s' is a rigid type variable bound by
      the type signature for append :: DVec s -> Int -> ST s (DVec s)
      at B.hs:11:11
Expected type: MVector (PrimState ((->) (DVec s))) Int
  Actual type: MVI1 s
In the first argument of `unsafeWrite', namely `y'
In the first argument of `(>>)', namely `unsafeWrite y i x'
In the expression: unsafeWrite y i x >> return
4

1 に答える 1

4

問題は、$演算子の優先順位が最も低いため、その左側のすべてが 1 つの関数として扱われることです。return $ DV (i+1) v使用する代わりにreturn (DV (i+1) v)

どうやってこれを理解したのですか?

タイプアノテーションを削除して、ghciがどのタイプを決定するかを確認しました。Ghci は、この制約のある型を検出しました(Control.Monad.Primitive.PrimMonad ((->) (DVec (PrimState m)))。これは、使用中の も関数であると ghci に思わせる何か問題があることを意味しPrimMonadます。($)その後、それがこの背後にある理由であることが明らかになりました。

于 2013-06-02T19:21:07.553 に答える