我有什麼做的,使GHC接受這個代碼:ST(U)數組在數據結構中?
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
module STTest where
import Data.Array.ST
import Control.Monad.ST.Strict as S
import Control.Monad.ST.Lazy as L
-- ST monad arrays (unboxed in actual code)
type Arr s a = STArray s Int a
-- representing some algorithm that works on these STArrays
data ArrGen s a = ArrGen (a -> S.ST s (Arr s a)) (Arr s a -> S.ST s())
-- class for some "generator"
class Generator g a where
gen :: g -> a -> [a]
instance Generator (ArrGen s a) a where
gen (ArrGen create apply) s = L.runST $ do
a <- strictToLazyST $ create s -- DOES NOT WORK
strictToLazyST $ apply a >> getElems a
我得到的錯誤是:
Couldn't match type `s' with `s1'
`s' is a rigid type variable bound by
the instance declaration at STTest.hs:20:28
`s1' is a rigid type variable bound by
a type expected by the context: L.ST s1 [a] at STTest.hs:21:33
然而,這工作得很好:
data Dummy
create' :: a -> S.ST s (Arr s a)
create' = undefined
apply' :: Arr s a -> S.ST s [a]
apply' = undefined
instance Generator Dummy a where
gen _ s = L.runST $ do
a <- strictToLazyST $ create' s
strictToLazyST $ apply' a >> getElems a
爲什麼它與第二個而不是第一個一起工作?我可以通過數據聲明來做些什麼?或者我可以在實例聲明中添加某種「全部」?
以上只是一個簡單的測試程序。我實際上循環應用永遠創建一個無限的輸出值流。 (所以我不能將這兩個步驟合併在一起。)我真的希望能夠爲ArrGen數據類型實例化一次,然後使用這些STArray算法爲其創建各種值。
編輯:
沒想到把FORALL的功能裏面ArrGen(我把它放在整體式)。儘管現在我有一個讓它在STUArray上工作的問題。就像如果我使用以下命令:
class (Integral a, Bits a, forall s. MArray (STUArray s) a (S.ST s)) => HasSTU a
type AC a = (HasSTU a) => forall s. a -> S.ST s (STUArray s Int a)
type AU a = (HasSTU a) => forall s. STUArray s Int a -> S.ST s()
type TX a = (HasSTU a) => a -> a -- or without the context
data ArrayGen a = AG (AC a) (AU a) (TX a)
那麼這個失敗:
instance (HasSTU a) => Generator (ArrayGen a) a [a] where
gens (AG c u p) s = fmap (fmap p) $ L.runST $ do
ar <- strictToLazyST $ (c s)
streamM $ strictToLazyST $ u ar >> getElems ar -- can't use getElems here!
streamM :: (Applicative f) => f a -> f (Stream a))
streamM = Cons <$> a <*> streamM a
它抱怨:
Could not deduce (MArray (STUArray s) a (S.ST s))
arising from a use of `getElems'
from the context (HasSTU a)
即使上下文(HasSTU一)說,(在我的腦海)那對於所有的s有一個(MArray(STUArray s)a(S.ST s))上下文,但似乎並不這麼認爲。我試圖通過更改(AU a)類型來修復它:
type AU a = (HasSTU a) => forall s. STUArray s Int a -> S.ST s [a]
而它似乎鍵入檢查,但我無法實際使用它。同樣的,如果我更改爲:
class (Integral a, Bits a, forall s. MArray (STUArray s) a (S.ST s)) => HasSTU s a
type AC a = (forall s. HasSTU s a) => a -> S.ST s (STUArray s Int a)
...
instance (forall s. HasSTU s a) => Generator (ArrayGen a) a [a] where
...
instance forall s. HasSTU s Word32 -- !!!
但是當我嘗試運行的東西:
Could not deduce (forall s. HasSTU s Word32)
我討厭這個S!爲什麼?我有一個所有 s!我真的失去了應該在哪裏放置我的論文以及發生了什麼。
謝謝你的回答!它讓我更靠近了一步......但我仍然無法使用STUArray。這非常令人沮喪!而且我已經接近放棄,並且始終只使用IArray,因爲ST monad讓我感覺完全失去了。我更新了我的問題,那裏有任何想法? – integer
編譯器是不是已經在class上完全禁用了(整數a,位a,全部s。MArray(STUArray s)a(S.ST s))=> HasSTU a'?如果不是,那麼什麼時候允許'forall'ed上下文呢?無論如何,沒有直接的想法如何做到這一點。如何使它成爲非ST的東西,並在每一步中使用'runST','unsafeThaw','unsafeFreeze'? –