2014-10-01 4 views
3

연습으로 저는 하스켈에서 명령 행 RPN 계산기를 작성하고 있습니다. 아이디어는 입력 (숫자 또는 연산자)을 요구하고 새로운 스택을 출력합니다. 내 계획은 상태 모나드에 숫자 목록을 저장하고 해당 목록에 대해 계산을 수행하는 것입니다. 예 :IO를 상태 계산과 혼합하기

> 4 
[4] 
> 3 
[3,2] 
> 5 
[5,3,2] 
> + 
[8, 2] 

등등.

각 항목에 입력 & 출력이있는 상태 모나드에서 목록을 작성하는 것으로부터 시작하고 있습니다. 나는 이미 동일한 기능의 IO & 상태의 조합으로 인해 막혔다. 내 문제는 첫 번째 숫자를 입력 한 후에 프롬프트를 계속 유지하려면 입력 내용을 재귀 적으로 처리해야한다는 것입니다.

module Main where 

import Control.Monad.State 

addEntry :: Int -> State [Int] Int 
addEntry entry = do 
    entries <- get 
    put (entry : entries) 
    return entry 

mainLoop :: [Int] -> IO() 
mainLoop entries = do 
    entry <- readLn 
    newEntries <- execState (addEntry entry) entries 
    print newEntries 
    mainLoop newEntries 

main :: IO() 
main = do 
    print $ mainLoop [] 

여기 나는 현재 받고 있어요 컴파일러 오류입니다 : 여기

지금까지 내 코드입니다

src/[email protected]:28-14:42 Couldn't match type [Int] with ‘IO [Int]’ 
Expected type: State (IO [Int]) Int 
    Actual type: State [Int] Int … 
src/[email protected]:44-14:51 Couldn't match expected type ‘IO [Int]’ with actual type [Int] … 

난하도록이 기능을 구성하는 방법에 대한 팁 IO & 상태를 결합하지 않습니까?

+1

'StateT [Int] Identity Int' ('State [Int] Int'와 동일) 대신 'StateT [Int] IO Int'를 사용하셨습니까? 그런 다음'liftIO'를 사용하여 IO 동작을 'StateT [Int] IO' 모나드로 옮기고 같은 동작 블록에서 상태 저장 연산과 IO 동작을 수행 할 수 있습니다. – bheklilr

+1

파일 상단에'{- # LANGUAGE FlexibleContexts # -}'를 추가하면'addEntry'의 타입 시그니처를'MonadState [Int] m => Int ->로 변경하면 컴파일 할 수 있습니다. m Int'로 변경 한 다음'execState'를'execStateT'로 변경하십시오.'print $ mainLoop []'와 컴파일러 오류가 있지만, 인쇄 자체를 수행하고 아무 것도 반환하지 않기 때문에'mainLoop []'이어야합니다 . [Like this] (https://gist.github.com/7331ab8d54ba17d82cae) – bheklilr

+0

실제 응용 프로그램에서 실제로 IO 랩핑 값을 사용자의 상태로 전달하는 것이 일반적입니까? 실제 상태 계산이 어떤 이유로 IO에 의존하지 않는다면, 그것은 나에게 상당히 더럽다고 느낍니다. –

답변

4

상태를 사용하고 싶다면 잘 모르겠지만 상태 모나드가 없으면 상태 자체를 얻을 수 있습니다.

module Main where 

addEntry :: Int -> [Int] -> [Int] 
addEntry = (:) 

mainLoop :: [Int] -> IO() 
mainLoop entries = do 
    entry <- readLn 
    let newEntries = addEntry entry entries 
    print newEntries 
    mainLoop newEntries 

main :: IO() 
main = mainLoop [] 
+0

나는 그것을 시험해보고 싶었다. 나는 일반적으로 모나드에 더 익숙해 지려고 노력하고있다. 그러나 그 이상으로 가능한 한 단순하게 유지하고 싶습니다. 그래서 이것은 매우 도움이됩니다! –