2014-11-24 4 views
3

Maybe을 사용하여 State 모나드를 결합하는 방법을 이해하려고하면 두뇌를 꼬집어 말합니다.상태 모나드에서 오류 처리에 대한 하스켈 예제 만들기

의 우리가 번호 목록의 합을 찾기 위해 State 모나드를 사용하는 콘크리트 (의도적 사소한/불필요) 예를 들어 시작하자 :

import Control.Monad.State 

list :: [Int] 
list = [1,4,5,6,7,0,3,2,1] 

adder :: Int 
adder = evalState addState list 

addState :: State [Int] Int 
addState = do 
    ms <- get 
    case ms of 
    []  -> return 0 
    (x:xs) -> put xs >> fmap (+x) addState 

쿨.

이제 목록에 숫자 0이 포함되어 있으면 Nothing을 반환하도록 수정 해 보겠습니다. 즉, evalState addState' listNothing을 반환해야합니다 (list에는 0이 포함되어 있기 때문에). 나는

addState' :: State [Int] (Maybe Int) 
addState' = do 
    ms <- get 
    case ms of 
    [] -> return (Just 0) 
    (0:xs) -> return Nothing 
    (x:xs) -> put xs >> fmap (fmap (+x)) addState' 

... 작동하지만이 할 수있는 더 좋은 방법이 생각 ...

내가 StateTMaybeT와 함께 놀았습니다 ... 그것은 다음과 같이 보일 줄 알았는데 나는 그들을 일하게 할 수 없다. Monad 트랜스포머에 대한 몇 가지 소개를 살펴 보았지만이 특정 콤보 (예 : State + Maybe)를 만지지 않았거나 예제가 너무 복잡해서 이해할 수 없었습니다.

TL; DR : 사람이 StateTMaybeT (두 가지 예)를 사용하여 코드의이 (틀림없이 사소한) 조각을 작성하는 방법을 보여줄 수 있다면 나는 감사하겠습니다. (나는 변압기를 사용하지 않고이 코드를 작성할 수 없다고 가정하고있다. 그 것은 틀린가?)

P. 내 이해는 StateT이이 예제에 더 적합 할 수 있지만 너무 많은 문제가 아니라면 개념적으로 두 예제를 보는 것이 도움이 될 것입니다.

업데이트 : @Brenton Alker가 지적한 것처럼 위의 코드는 간단한 오타 (apostrophe가 누락 됨)로 인해 작동하지 않습니다. StateT/MaybeT의 사용에 관한 질문에 초점을 맞추기 위해 위 게시물을 수정하려고합니다. 이 메모를 포함하여 자신의 게시물에 대한 컨텍스트를 제공하고 싶었습니다. 내가 사용하는 것이 좋습니다 것입니다

답변

8

유형은 다음과 같습니다

StateT [Int] Maybe Int 

정말 간단한 방법은 실패한 계산에서 복구 할 때마다 mplus 실패 할 때마다 Maybe/MaybeT 그냥 mzero를 호출하는 것입니다 사용할 수 있습니다. 이것들은 다른 모나드 변압기 내에 겹쳐 쌓여 있어도 작동합니다. 내가 쓴

addState' :: StateT [Int] Maybe Int 
addState' = do 
    ms <- get 
    case ms of 
    []  -> return 0 
    (0:xs) -> mzero 
    (x:xs) -> put xs >> fmap (fmap (+x)) addState 

-- This requires generalizing the type of `addState` to: 
addState :: Monad m => StateT [Int] m Int 

공지 사항 난 어떤 Maybe - 특정 작업을 사용하지 않은 그런 방법 :

다음은 예입니다.컴파일러가 타입 서명을 추정 할 경우 사실, 대신보다 일반적인 유형을 추론합니다

instance MonadPlus m => MonadPlus (StateT s m) where ... 

그리고 Maybe이 붙이 것이다 StateT 다음 MonadPlus 인스턴스를 가지고 있기 때문에

addState' :: MonadPlus m => StateT [Int] m Int 

이 작동 MonadPlus의 인스턴스로 확인하십시오. 따라서 mMaybe으로 전문화하면 위 코드가 작동합니다.

+0

이 'StateT' 함수를 어떻게 실행합니까? 코드가 컴파일됩니다 (@Brenton Alker가 지적한 원래 게시물의 아포스트로피를 수정한다고 가정). 그러나 다음을 사용하여 실행할 수 없습니다 (GHCi에서) : 'evalState addState'list'. 어떤 제안? – iceman

+2

@DipakC,'evalStateT' – luqui

1

귀하의 솔루션이 기본적으로 정확하다고 생각합니다. 몇 가지 사소한 문제가 있습니다.

  1. addState에 대한 재귀 호출에 소수가 누락되었습니다. 즉. 그것은 addState'이어야합니다 (이것은 단지보고 된 오류가 주어진 질문에 붙여 넣기에 문제가 있다고 생각합니다).
  2. adder :: Int을 주장하고 있지만 새 버전에서는 adder :: Maybe Int이어야합니다 - 이것은 유형 오류라고 생각합니다. 다시지고.

불행히도 현재로서는 변압기 버전을 사용해 볼 수있는 리소스가 없습니다.

+0

예, 당신은 정말로 틀림 없습니다 : 아포스트로피 ... * 붉은 얼굴 * – iceman