I want to implement a dynamic programming algorithm that is polymorphic in the type of evaluation; here is a simplified version of 1D without boundary conditions:
{-# LANGUAGE ConstraintKinds, FlexibleContexts, RankNTypes, ScopedTypeVariables #-} import Control.Monad import Control.Monad.ST.Strict import Data.Array.ST import Data.Array.Unboxed dynamicProgrammingSTU :: forall ei . ( IArray UArray e, forall s. MArray (STUArray s) e (ST s), Ix i ) => (forall m . Monad m => (i -> me) -> (i -> me)) -> (i, i) -> (i -> e) dynamicProgrammingSTU prog bnds = (arr !) where arr :: UArray ie arr = runSTUArray resultArrayST resultArrayST :: forall s . ST s (STUArray sie) resultArrayST = do marr <- newArray_ bnds forM_ (range bnds) $ \i -> do result <- prog (readArray marr) i writeArray marr i result return marr
The restriction does not work;
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 - > me) -> i -> me) -> (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 sie) or the type signature for dynamicProgrammingSTU :: (IArray UArray e, forall s. MArray (STUArray s) e (ST s), I xi) => (forall (m :: * -> *). Monad m => (i -> m e) -> i -> me) -> (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.
To summarize, Could not deduce (MArray (STUArray s) e (ST s)) from the context forall s. MArray (STUArray s) e (ST si) Could not deduce (MArray (STUArray s) e (ST s)) from the context forall s. MArray (STUArray s) e (ST si) . Note that adding a constraint to resultArrayST just pushes the problem to runSTUArray .
Currently, I know of four erroneous decisions:
- Avoid problems with the
STArray box or just non-monodic Array s, possibly using seq and bang patterns to alleviate the memory problems that arise. - Violation of the type system with
unsafeFreeze and unsafePerformIO , for which the restriction of protection MArray IOUArray e IO works fine. - This is a solution to a similar problem using an instance of typeclass and an entry for each type of "unboxable".
- This one uses GHC rewrite rules to select a different function for each type (and the generic version of
STArray ).
However, I ask this question in the hope that modern language extensions such as ConstraintKinds can allow me to express my original intention for the forall s. MArray (STUArray s) e (ST s) code forall s. MArray (STUArray s) e (ST s) forall s. MArray (STUArray s) e (ST s) .
source share