2016-11-28 2 views
7

내가 Learn you a haskell 책을 통해 갈거야, 그리고 제 8 장에서이 작품이하스켈 - case 문

data LockerState = Taken | Free deriving (Eq, Show) 
type Code = String 
type LockerMap = Map.Map Int (LockerState, Code) 

lookup' :: Int -> LockerMap -> Either String Code 
lookup' num_ map_ = 
    case (Map.lookup num_ map_) of 
     Nothing -> Left $ "LockerNumber doesn't exist!" 
     Just (state, code) -> if state == Taken 
           then Left $ "LockerNumber already taken!" 
           else Right $ code 

과 같은 코드의 조각이 내부 가드. 그러나 if/else 블록을 다음과 같이 보호해야합니다.

lookup' :: Int -> LockerMap -> Either String Code 
lookup' num_ map_ = 
    case (Map.lookup num_ map_) of 
     Nothing -> Left $ "LockerNumber doesn't exist!" 
     Just (state, code) -> 
     | state == Taken = Left $ "LockerNumber already taken!" 
     | otherwise = Right $ Code 

이것은 컴파일되지 않습니다. 하스켈에서 경비원의 사용은 매우 제한적/비 직관적 인 것으로 보인다. SO Ex1SO Ex2. 경비원을 사용할 수있는 장소를 알려주는 확실한 출처가 있습니까?

답변

18

가드가 허용되는 위치는 함수 정의와 case 두 가지입니다. 두 상황에서, 경비원 이전 패턴과 몸 후 표시, 그래서 당신은 평소와 같이, case 지점에서 함수의 =->를 사용

divide x y 
    | y == 0 = Nothing 
    -------- 
    | otherwise = Just (x/y) 
    ----------- 

positively mx = case mx of 
    Just x | x > 0 -> Just x 
     ------- 
    _ -> Nothing 

가드가 제약 패턴 그래서, 단순히 Just xNothing 값과 일치하지만 Just x | x > 0은 랩핑 된 값이 양수인 Just과 일치합니다.

나는 결정적인 기준이 구체적으로 경비의 구문을 설명하고 그들이 사용할 수있는 위치를 지정 § 3.13 사례 식 및 § 4.4.3 기능 및 패턴 바인딩의 Haskell Report 가정하자. 코드에서

은, 당신이 원하는 :

Just (state, code) 
    | state == Taken -> Left "LockerNumber already taken!" 
    | otherwise -> Right code 

이것은 또한 단독 패턴을 표현할 수있다 :

Just (Taken, _) -> Left "LockerNumber already taken!" 
Just (_, code) -> Right code 
+1

멋진 대답을! 특히'가드는 단순한 패턴의 제약이다. ' – skgbanga