2012-08-13 3 views
1

나는 Haskel에서 Maybe-idiom을 적용하는 방법을 이해하려고 노력 중입니다 ... http://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe은 사전에서 조회가 Maybe을 반환하고이 값이 >>= 연산자를 통해 전달됨을 보여줍니다.오류 처리 및 모나드?

URL의 예 :

우리는 다음 (우리는 그들이 어떤 자동차 세를 빚지고 있는지 확인하기 위해 자신의 등록 번호를 조회하고 싶은 말) 세 번째 조회에 정부 데이터베이스 검색에서 결과를 사용하고자하는 경우

getTaxOwed name = do 
    number  <- lookup name phonebook 
    registration <- lookup number governmentalDatabase 
    lookup registration taxDatabase 

질문 : DO-블록 스타일을 사용하여,

getTaxOwed :: String  -- their name 
      -> Maybe Double -- the amount of tax they owe 
getTaxOwed name = 
    lookup name phonebook >>= 
    (\number -> lookup number governmentalDatabase) >>= 
     (\registration -> lookup registration taxDatabase) 

또는 :, 우리는 우리의 getRegistrationNumber 기능을 확장 할 수 :

오류 처리는 어떻게 처리합니까? 나는 대부분의 코드가 일이 잘못되었다는 것을 알면 도움이 될 것이라고 생각한다. 단순히 "전화 번호부 또는 정부 데이터베이스에서 John Doe를 찾을 수 없음"을보고하기보다는 어떤 자원에 문제가 있는지보고해야합니다.

+1

당신이 발견 한 것은 아마 하나의 가능한 실패 사례가있을 경우 Maybe가 가장 유용하다는 것입니다. 음수의 제곱근을 생각하십시오. 반면에'sqrt :: Either Complex Double'을 만들 수 있습니다. – Sarah

+0

네, 맞습니다. 여기 http://hackage.haskell.org/packages/archive/transformers/0.3.0.0/doc/html/Control-Monad-Trans-Error.html 문제에 대한 일반적인 해결책이 있습니다. 아마도 정확한 오류 처리에 관한 것이 아닙니다. – permeakra

답변

8

에서 당신은 본질적으로

instance Monad (Either String) where            
    fail msg = Left msg                
    return x = Right x                

    Left msg >>= k = Left msg              
    Right x >>= k = k x 

로 정의 Either String위한 모나드 인스턴스를 사용할 수 있다는 것을 사용하는 방법에 대해 자세히 알아

하는 경우 우리는 사전과 룩업 테이블로 구성된 쌍으로 사전을 정의한다.

type Dict a b = (String, [(a, b)]) 

phonebook' :: Dict String Int 
phonebook' = ("phone book", phonebook) 

governmentalDatabase' :: Dict Int Int 
governmentalDatabase' = ("governmental database", governmentalDatabase) 

taxDatabase' :: Dict Int Double 
taxDatabase' = ("tax database", taxDatabase) 

여기서이제 모나드의 힘을 보여주는

lookup' :: (Eq a, Show a) => a -> Dict a b -> Either String b 
lookup' key (descr, table) = case lookup key table of 
    Nothing -> Left ("couldn't find " ++ show key ++ " in " ++ descr) 
    Just val -> Right val 

, 유일한 :, governmentalDatabasetaxDatabase 당신이 그들 이전에 정의했던대로, 우리가 Either String -monad에 그 결과를 반환하는 다른 모나드 조회 기능을 사용할 수 있습니다 클라이언트 기능에 변경해야하는 유형 서명입니다 :

getTaxOwed :: String    -- their name         
      -> Either String Double -- either an error message      
            -- or the amount of tax they owe    
getTaxOwed name = do 
    number  <- lookup' name phonebook' 
    registration <- lookup' number governmentalDatabase' 
    lookup' registration taxDatabase' 

알 수없는 이름이 기능을 실행 제공 :

> getTaxOwed "Joe" 
Left "couldn't find \"Joe\" in phone book" 
5

아마도 데이터 유형에는 오류를 알리는 값 "Nothing"만 있습니다. 특정 오류 메시지를 반환하려면 "왼쪽"또는 "오른쪽"값 중 하나를 반환 할 수있는 "모두"데이터 형식을 제안합니다. (실제 정의는 조금 더 복잡하다.) http://learnyouahaskell.com/for-a-few-monads-more#error