タイプのインプレースベクトル関数が多数あります。
f :: (M.MVector v r, PrimMonad m) =>
v (PrimState m) r -> v (PrimState m) r -> m ()
これらの関数はほとんどの場合その場で動作するため、それらの引数を変更可能なベクトルにして、作成、反復などを行うことができると便利です。ただし、最上位レベルでは、不変の「Haskell」/純粋なベクトルのみを使用したいと考えています。 .
問題の例を次に示します。
{-# LANGUAGE TypeFamilies,
ScopedTypeVariables,
MultiParamTypeClasses,
FlexibleInstances #-}
import Data.Vector.Generic as V hiding (eq)
import Data.Vector.Generic.Mutable as M
import Control.Monad.ST
import Control.Monad.Primitive
f :: (M.MVector v r, PrimMonad m) =>
v (PrimState m) r -> v (PrimState m) r -> m ()
f vIn vOut = do val <- M.read vIn 0
M.write vOut 0 val
applyFunc :: (M.MVector v r, PrimMonad m, V.Vector v' r, v ~ Mutable v') =>
(v (PrimState m) r -> v (PrimState m) r -> m ()) -> v' r -> v' r
applyFunc g x = runST $ do
y <- V.thaw x
g y y -- LINE 1
V.unsafeFreeze y
topLevelFun :: (V.Vector v r) => r -> v r
topLevelFun a =
let x = V.replicate 10 a
in applyFunc f x -- LINE 2
記述されたコードでは、LINE 1 でエラーが発生します。
Could not deduce (m ~ ST s)
Expected type: ST s ()
Actual type: m ()
in the return type of g, LINE 1
LINE 1 をコメントアウトすると、LINE 2 でエラーが発生します。
Ambiguous type variable `m0' in the constraint:
(PrimMonad m0) arising from a use of `applyFun'
さまざまな明示的な型付け (ScopedTypeVariables、明示的な foralls などを使用) を試しましたが、最初のエラーを修正する方法が見つかりませんでした。m
LINE 1 エラーについてはST s
、runST
.
LINE 2エラー(LINE 1がコメントアウトされている)の場合、私が思いついた唯一のことは
class Fake m v where
kindSig :: m a -> v b c
instance Fake m v
topLevelFun :: forall m v v' r . (V.Vector v' r, M.MVector v r, PrimMonad m, Fake m v, v ~ Mutable v') => r -> v' r
topLevelFun a =
let x = V.replicate 10 a
in applyFunc (f::Transform m v r) x -- LINE 2
これは明らかに満足のいくものではありません。偽のクラスを作成する必要があり、クラス引数の種類を示すことだけが仕事であるさらに無意味なメソッドを使用します。次に、すべての汎用インスタンスを作成してm
、スコープ内でtopLevelFun
を使用できるようにし、制約を追加して をキャストできるようにしますf
。もっと良い方法があるはずです。
ここでさまざまなことを間違っている可能性があるため、提案があれば役立ちます。