2017-03-05 7 views
0

간단한 변수로 State Monad를 사용하려고했는데 제대로 작동했습니다. 하지만 여기에 내가 혼합 입출력과 비 입출력을 시도하는 것 같습니다. 상태 모나드가 관리하는 배열을 가질 의도입니다. 이 배열을 읽고 쓰고 싶습니다.State Monad IO와 non-IO를 섞음

내가 생각했던 것보다 더 열심히 보입니다.

 funarray :: Map.Map String (IOArray Int Int) 
     funarray = Map.empty 

     storearray :: String -> (IOArray Int Int)-> State (Map.Map String (IOArray Int Int))() 
     storearray x value = do 
     funarray <- get 
     put (Map.insert x value funarray) 

     retrievearray :: String -> State (Map.Map String (IOArray Int Int)) (Maybe ((IOArray Int Int))) 
     retrievearray arr = do 
     funarray <- get 
     return (Map.lookup arr funarray) 

     putmutablearray = do { 
        arr <- newArray (512,512) 0 ; 
        storearray "value-table" arr 
       } 
     getmutablearray = do { retrievearray "value-table";} 

     putthenget = do {putmutablearray; getmutablearray;} 

     value :: BoardState -> IO Int 
     value (BoardState xloc oloc index) = do { 
      arr <- (runState putthenget funarray); 
      v <- (readArray arr index); 
      return v 
     } 

여러 오류가 있습니다.

* Couldn't match expected type `IOArray Int Int' 
       with actual type `IO (IOArray Int Int)' 
* In the second argument of `storearray', namely `createarray' 
    In a stmt of a 'do' block: storearray "value-table" createarray 
    In the expression: do { storearray "value-table" createarray } 

혼합 할 수 있습니까?

이것은 단지 글로벌 배열입니다. 큰 것. 기계 학습 과제를 위해 큰 것들이 필요합니다.

업데이트 : 필수 언어로 전 세계적으로 이것을 저장할 것입니다.

  createarray :: IO (IOArray Int Int) 
      createarray = do { 
        arr <- newArray (512,512) 0; 
        return arr 
       } 
+1

당신이 생각해 낸 해결책에 문제가있는 것처럼 느껴집니다. 당신이 달성하고자하는 것에 대해 좀 더 많은 맥락을 우리에게 줄 수 있습니까? – epsilonhalbe

+1

친절하고 모든 함수 정의에 서명을 추가하십시오. 따라서 함수가 예상대로 작동하는지 확인하십시오. – epsilonhalbe

+0

상태 모나드의 상태를 업데이트하고 (배열에 대한) IO 액세스를 수행하는 것처럼 보입니다. 당신은 동시에 그것을 할 수 없습니다 : 당신은 주 모나드에서 일하거나 입니 다. 두 가지 작업을 모두 원한다면 두 가지를 모두 허용하는 모나드를 선택해야합니다. 'StateT (IOArray ...) IO'는 모나드 변압기를 사용하고'liftIO'는 IO 동작을 임베딩합니다. 이것은 모나드에 대한 몇 가지 고급 지식을 요구합니다. 그러나, 아마도 당신이 필요로하는 것은 그것보다 훨씬 간단합니다. 당신은 당신의 과제에 대해 더 잘 설명해야합니다 : state monad + IO arrays + IO + Map을 사용하는 것은 조금 이상합니다. – chi

답변

0

내 대답. 나는 이것이 하스켈의 관용적 인 답이라고 생각한다. 다른 전문가도 의견을 말할 수 있습니다. 배열을 전역 적으로 액세스 가능하게 만드는 방법을 모르겠습니다. 하스켈이 맞지 않다고 들었습니다.

type ArrayAccess = ReaderT (IOArray Int Int) IO 
    type ArrayWriteAccess = ReaderT (IOArray Int Int) IO() 

    readvalue :: Int -> ArrayAccess Int 
    readvalue x = do 
    a <- ask 
    b <- liftIO(readArray a x);  
    return b 

    writevalue :: Int -> Int -> ArrayWriteAccess 
    writevalue x y = do 
    a <- ask 
    liftIO(writeArray a x y)  

    -- Test array accesses 
    readfromarray = do { a <- createarray; liftIO (runReaderT (readvalue 1) a) } 
    writetoarray = do { a <- createarray; liftIO (runReaderT (writevalue 1 2) a) }