ST-Monad とボックス化されていない STArray (STUArray) を使用して、行列の行列式を見つける関数を作成しました。マトリックスの型は次のとおりです。
newtype Matrix e = Matrix (Array Int (UArray Int e))
つまり、要素を含む不変のボックス化されていない配列を含む不変の配列です。IArray UArray e
これには、を扱う関数に Predicate を追加する必要がありMatrix
、これにはFlexibleContexts
. わかりました。
行列式の計算に使用される関数には、次のシグネチャがあります。
detST :: (IArray UArray e, MArray (STUArray s) e (ST s),
Num e, Eq e, Division e)
=> Array Int (UArray Int e) -> ST s e
MArray (STUArray s) e (ST s)
内部で配列が可変配列 (外側はボックス化され、内側はボックス化されていない) に変換されるため、Predicate も追加する必要があります。
この関数は次のように使用できます。
main = do
let m@(Matrix x) = matrix [ [1,-2,3,234]
, [5,2,3,-3]
, [7,18,3,40]
, [2,9,71,0] ]
d = runST (detST x) :: Int -- needed for type check, ambiguous otherwise
print d
正常に動作します。しかし、それがどれほど醜いか見てください!もちろん、of の内部構造を公開したくはありませんMatrix
(少なくとも、関数に付加された述語が既に私に与えている以上のことはしません)。次の関数を定義したいと思います。
det :: Matrix e -> e
そして、私はできません。
適切な署名なしで試しました:
det (Matrix arr) = runST (detST arr)
失敗します。結構です、私は頭を働かせます:がdetST
必要です。IArray UArray e, MArray (STUArray s) e (ST s), Num e, Eq e, Division e
det
det :: (IArray UArray e, MArray (STUArray s) e (ST s),
Num e, Eq e, Division e) => Matrix e -> e
失敗します。しかし、方法がわかりません。GHC ( 7.4.2 ) が私に与えるメッセージは次のとおりです。
Could not deduce (MArray (STUArray s) t (ST s))
arising from a use of `detST'
しかし、その正確な用語は述語にあります!
GHC は次のことを提案します。
add (MArray (STUArray s) t (ST s)) to the context of
a type expected by the context: ST s t
or the inferred type of
det :: (Eq t, Num t, IArray UArray t, Division t) => Matrix t -> t
or add an instance declaration for (MArray (STUArray s) t (ST s))
わかった。私の理解では、私はそれを最初に行いました。また、そのためのインスタンスが存在します(MArray ...)
(そうでなければ、どうすればそれをメインでうまく使用できたでしょうか?!)。
ここで何が悪いのかわかりません。の「隠された」ST状態と関係s
があり、 のはindetST
以外s
のものであると思いますが、これの型を書く方法がわかりません。s
det
の適切な定義は何ですかdet
- そしてその理由は?!
なしのプログラムは、det
のみを使用して正常にコンパイルされFlexibleContexts
、警告はありません-Wall
。完全なソース コードは、ここで要旨として見つけることができます。