スコア型で動的プログラミングアルゴリズム多相を実装したいと思います。境界条件のない簡略化された1Dバージョンです:制約の種類を持つ多態性STUArraysの再訪
{-# LANGUAGE ConstraintKinds, FlexibleContexts, RankNTypes, ScopedTypeVariables #-}
import Control.Monad
import Control.Monad.ST.Strict
import Data.Array.ST
import Data.Array.Unboxed
dynamicProgrammingSTU
:: forall e i . (
IArray UArray e,
forall s. MArray (STUArray s) e (ST s),
Ix i
)
=> (forall m . Monad m => (i -> m e) -> (i -> m e))
-> (i, i)
-> (i -> e)
dynamicProgrammingSTU prog bnds = (arr !) where
arr :: UArray i e
arr = runSTUArray resultArrayST
resultArrayST :: forall s . ST s (STUArray s i e)
resultArrayST = do
marr <- newArray_ bnds
forM_ (range bnds) $ \i -> do
result <- prog (readArray marr) i
writeArray marr i result
return marr
制約は機能しません。
Could not deduce (MArray (STUArray s) e (ST s))
arising from a use of `newArray_'
from the context (IArray UArray e,
forall s. MArray (STUArray s) e (ST s),
Ix i)
bound by the type signature for
dynamicProgrammingSTU :: (IArray UArray e,
forall s. MArray (STUArray s) e (ST s
), Ix i) =>
(forall (m :: * -> *). Monad m => (i -
> m e) -> i -> m e)
-> (i, i) -> i -> e
at example2.hs:(17,1)-(27,15)
Possible fix:
add (MArray (STUArray s) e (ST s)) to the context of
the type signature for resultArrayST :: ST s (STUArray s i e)
or the type signature for
dynamicProgrammingSTU :: (IArray UArray e,
forall s. MArray (STUArray s) e (ST s), I
x i) =>
(forall (m :: * -> *). Monad m => (i -> m
e) -> i -> m e)
-> (i, i) -> i -> e
or add an instance declaration for (MArray (STUArray s) e (ST s))
In a stmt of a 'do' block: marr <- newArray_ bnds
In the expression:
do { marr <- newArray_ bnds;
forM_ (range bnds) $ \ i -> do { ... };
return marr }
In an equation for `resultArrayST':
resultArrayST
= do { marr <- newArray_ bnds;
forM_ (range bnds) $ \ i -> ...;
return marr }
Failed, modules loaded: none.
要約すると、Could not deduce (MArray (STUArray s) e (ST s)) from the context forall s. MArray (STUArray s) e (ST s i)
。 resultArrayST
に制約を追加すると、問題はrunSTUArray
にプッシュされます。
私は現在、4つの欠陥のある解決策を知っている:
- おそらく結果としてメモリの問題を緩和するために
seq
と強打のパターンを使用して、箱入りSTArray
Sまたは単に非モナドArray
sの問題を回避します。 unsafeFreeze
とunsafePerformIO
で型システムを打ち切っています。そのためには、制約条件MArray IOUArray e IO
が問題なく動作します。- This同様の問題を解決するには、型クラスを使用し、インスタンスを 'unboxable'型ごとに記述します。
- This GHC書き換えルールを使用して、それぞれのタイプごとに異なる機能(および一般的な
STArray
バージョン)を選択するものです。
しかし、私はConstraintKinds
のような近代的な言語拡張は私がforall s. MArray (STUArray s) e (ST s)
の私の元のコードの意図を表現できるようにすることができますことを期待して、この質問をしています。
ghc-7.6.1は ''不正な述語 ''と言っています。 MArray(STUArray s)e(ST s) '''は、私にはより意味があります。 –
'prog'関数が単にパフォーマンスのためのモナドである場合、私はあなたのpと思っています。 1(可能性のあるバンパターンを含む純粋な計算)は、最も悪いことではありません。 – leventov