Desidero implementare un algoritmo di programmazione dinamica polimorfico nel tipo di partitura; Ecco una versione 1D semplificata senza condizioni limite:Rivisitazione di STUArray polimorfi con tipi di vincoli
{-# 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
Il vincolo non funziona;
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.
Per riepilogare, Could not deduce (MArray (STUArray s) e (ST s)) from the context forall s. MArray (STUArray s) e (ST s i)
. Si noti che aggiungendo il vincolo a resultArrayST
è sufficiente trasferire il problema a runSTUArray
.
Io attualmente a conoscenza di quattro soluzioni imperfetti:
- Evitando il problema con boxed
STArray
s o semplicemente non monadiciArray
s, magari utilizzandoseq
e bang modelli per alleviare i problemi di memoria che ne derivano. - Interruzione del sistema di tipi con
unsafeFreeze
eunsafePerformIO
, per il quale il vincolo dannosoMArray IOUArray e IO
funziona correttamente. - This soluzione a un problema simile utilizzando un typeclass e le istanze di scrittura per ogni tipo 'Unboxable'.
- This uno utilizza le regole di riscrittura GHC per selezionare una funzione diversa per ogni tipo (e una versione generica
STArray
).
Tuttavia, mi sto chiedendo questa domanda nella speranza che estensioni del linguaggio moderni, come ConstraintKinds
può permettere di esprimere l'intento del mio codice originale di forall s. MArray (STUArray s) e (ST s)
.
ghc-7.6.1 dice "predicato malformato" per tutti i s. MArray (STUArray s) e (ST s) ''', che per me ha più senso. –
Se la funzione 'prog' è monadica solo per le prestazioni, penso che la tua p. 1 (calcoli puri con probabili schemi di scoppio) sarebbe il minimo dei mali. – leventov