リストのサイズとともにリストを取得することになっている関数をhaskellで作成しました。そして、指定されたサイズでData.Vector.Mutable.MVectorを作成し、リストの内容をベクトルに入力して、このベクトルを返すことになっています。
TL; DR
これは機能です:
vecFromList lst sz = MV.new sz >>= (\vec -> fillV (zip [0..sz - 1] lst) vec) where
fillV [] vec = vec
fillV ((i, v):xs) vec = MV.write vec i v >> fillV xs vec
そのほとんどは、彼らが何をしているのか(最後の行)を実際に理解しようとせずに書いたものであり、その結果、適切な型の署名を思い付くことができません。しかし、コンパイラーはこれでその日を救うために介入しました:
コンパイラが生成した型シグネチャ
vecFromList
:: (PrimMonad (MVector t), PrimState (MVector t) ~ t) =>
[b] -> Int -> MVector t b
誰かがワットと言うのを聞きましたか?とにかく、それは私だけでした...コンパイルを試みる前に、これは私が機能するはずだと思ったタイプシグネチャです。
私が思ったものはうまくいくはずです
vecFromList :: PrimMonad m => [t] -> Int -> MV.MVector (PrimState m) t
この時点で、私が関数に実行させたいこととまったく同じように見えるこのやや単純な外観の型シグネチャが実際には機能しないことは明らかです。型シグニチャを思い付くために、私はベクトルモジュール内の他のいくつかの関数の型シグニチャを使用していました。たとえば、次のようなものです。
Data.Vector.Mutable.read
:: PrimMonad m => MVector (PrimState m) a -> Int -> m a
今、私はまだhaskellに比較的慣れていないので、言語で使用される記号や記号に慣れようとしています。特に、単純なタスクのように見えるものが、モナンドのためにこのように複雑なものにならなければならない理由を理解しようとしています。たとえば、MVector
この種の目的は何MVector :: * -> * -> *:
ですか?
もうすぐです。結果MVector
がモナドにある必要があることを除いて、型シグネチャが正しいことが期待されますm
:
vecFromList :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t)
fillV
機能はタイプを持っている必要があります
fillV :: [(Int, t)]
-> MV.MVector (PrimState m) t -> m (MV.MVector (PrimState m) t)
しかし、あなたはそれを型に付け[]
ずにベクトルを与える場合です。動作するバージョンは次のとおりです。return
m
vecFromList :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t)
vecFromList lst sz = MV.new sz >>= (\vec -> fillV (zip [0..sz - 1] lst) vec) where
fillV [] vec = return vec
fillV ((i, v):xs) vec = MV.write vec i v >> fillV xs vec
と実用的な例:
> V.create $ vecFromList [1,2,3] 3
fromList [1,2,3]
関数を実際に変更するのvec
ではなくfillV
、参照するだけであることに注意してください。明示的にループを作成する代わりに、for_
から関数を使用できData.Foldable
ます。私は通常、可変のベクトルコードをdo
ブロックで記述します。これは、状況が明確になるためです。
vecFromList2 :: PrimMonad m => [t] -> Int -> m (MV.MVector (PrimState m) t)
vecFromList2 l n = do
v <- MV.new n
for_ (zip [0..n - 1] l) $ \(i,a) -> MV.write v i a
return v
残念ながら、Haskellで可変ベクトルを操作するのは難しい場合があり、練習が必要です。TypedHolesとPartialTypeSignaturesを使用すると役立ちます。
ReasonMVector
にはPrimState m
それがあるので、ST
またはで動作しIO
ます。あなたはそれの説明をここで見つけることができます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加