2014-05-10 2 views
8

내가 쓴 작은 프로그램을 변경할 수 벡터를 넣어 복잡성 그리고 O (1)에서 업데이트를 찾고 O (1)에서 액세스하고 있습니다. 가변 벡터는 내가 원하는 것을합니다. 이들을 사용하려면 ST 또는 IO를 사용해야합니다. 나는 UnitTests를하고 싶기 때문에 ST 모나드를 선호하지만, 함수 호출에서 그 벡터를 전달하고 싶지는 않습니다. ErrorT와 WriterT 같은 변압기를 추가 할 것이므로 Monad Transformers를 계속 사용해야합니다.어떻게 벡터와 국가 모나드를 사용하여 트리에 Int 인 값의 모든 ocurences를 계산 하스켈 주 모나드에

질문 : Monad Transformers를 사용하여 상태 모나드에 가변 벡터를 삽입하는 방법은 무엇입니까?

import Data.Vector 
import Control.Monad.State 
import Control.Monad.Identity 
import qualified Data.Vector.Mutable as VM 
import Control.Monad.ST 
import Control.Monad.ST.Trans 
type MyMon2 s a = StateT (VM.MVector s Int) (STT s Identity) a 

data Tree a = Null | Node (Tree a) a (Tree a) deriving Show 
main :: IO() 
main = do 
    print $ runTraverse (Node Null 5 Null) 

runTraverse :: Tree Int -> ((),Vector Int) 
runTraverse t = runIdentity (Control.Monad.ST.Trans.runST $ do 
     emp <- VM.replicate 7 0 
     (_,x) <- (runStateT (traverse t) emp) 
     v <- Data.Vector.freeze x 
     return ((), v) 
    ) 
traverse :: Tree Int -> MyMon2 s() 
traverse Null = return() 
traverse (Node l v r) = do 
    d <- get 
    a <- (VM.read d v) 
    VM.write d v (a + 1) 
    put d 
    return() 

컴파일 오류는 다음과 같습니다 :

TranformersExample: line 16, column 16: 
    Couldn't match type `s' 
        with `primitive-0.5.2.1:Control.Monad.Primitive.PrimState 
          (STT s Identity)' 
     `s' is a rigid type variable bound by 
      a type expected by the context: STT s Identity ((), Vector Int) 
      at test/ExecutingTest.hs:15:30 
    Expected type: STT s Identity (MVector s Int) 
     Actual type: STT 
        s 
        Identity 
        (MVector 
         (primitive-0.5.2.1:Control.Monad.Primitive.PrimState 
          (STT s Identity)) 
         Int) 
    In the return type of a call of `VM.new' 
    In a stmt of a 'do' block: emp <- VM.new 7 
    In the second argument of `($)', namely 
     `do { emp <- VM.new 7; 
      (_, x) <- (runStateT (traverse t) emp); 
      v <- freeze x; 
      return ((), v) }' 
TranformersExample: line 26, column 14: 
    Couldn't match type `s' 
        with `primitive-0.5.2.1:Control.Monad.Primitive.PrimState 
          (StateT (MVector s Int) (STT s Identity))' 
     `s' is a rigid type variable bound by 
      the type signature for traverse :: Tree Int -> MyMon2 s() 
      at test/ExecutingTest.hs:21:13 
    Expected type: MVector 
        (primitive-0.5.2.1:Control.Monad.Primitive.PrimState 
         (StateT (MVector s Int) (STT s Identity))) 
        Int 
     Actual type: MVector s Int 
    In the first argument of `VM.write', namely `d' 
    In a stmt of a 'do' block: VM.write d v (a + 1) 
    In the expression: 
     do { d <- get; 
      a <- (VM.read d v); 
      VM.write d v (a + 1); 
      put d; 
      .... } 

참고 :

나는 컴파일되지 않습니다 다음 코드를 내놓았다을 내가 경계를 확인하지 알고있다.

답변

13

ST 상태를 사용하면 (즉, s 인수에 숨겨진에서 항상) 결코 명시 적으로 주변의 벡터를 통과,하지만에 대한 참조. 이 참조는 변경 불가능하고 복사되지 않으므로 State을 필요로하지 않고 단순히 암시 적으로 전달하는 독자입니다.

import Data.Vector 
import Control.Monad.Reader 
import qualified Data.Vector.Mutable as VM 
import Control.Monad.ST 

type MyMon3 s = ReaderT (VM.MVector s Int) (ST s) 

data Tree a = Null | Node (Tree a) a (Tree a) deriving Show 
main :: IO() 
main = do 
    print $ runTraverse (Node Null 5 Null) 

runTraverse :: Tree Int -> Vector Int 
runTraverse t = runST $ do 
     emp <- VM.replicate 7 0 
     runReaderT (traverse t) emp 
     Data.Vector.freeze emp 

traverse :: Tree Int -> MyMon3 s() 
traverse Null = return() 
traverse (Node l v r) = do 
    d <- ask 
    a <- lift $ VM.read d v 
    lift $ VM.write d v (a + 1) 
+0

감사합니다. 그게 내가 필요한 것입니다. – user2746253

+0

이것은 STVector에 대한 이해를 도왔습니다. –

관련 문제