Haskell-guard内部案例陈述

Haskell-guard内部案例陈述,haskell,pattern-guards,Haskell,Pattern Guards,我正在浏览这本书,在第8章中有一段代码,看起来像这样 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_ m

我正在浏览这本书,在第8章中有一段代码,看起来像这样

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

这不能编译。Haskell中警卫的使用似乎非常严格/不直观。有没有一个确切的来源,我可以阅读,告诉我在哪些地方可以使用警卫

有两个地方是允许的:函数定义和
case
表达式。在这两种情况下,防护装置都出现在图案之后和主体之前,因此您可以像往常一样在函数中使用
=
,在
案例中使用
->

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

positively mx = case mx of
  Just x | x > 0 -> Just x
         -------
  _ -> Nothing
防护只是模式的约束,因此
Just x
匹配任何非
Nothing
值,但
Just x | x>0
仅匹配包装值也是正的
Just

我认为最终参考是,特别是§3.13 Case表达式和§4.4.3函数和模式绑定,它们描述了保护的语法并指定了允许它们的位置

在代码中,您需要:

Just (state, code)
  | state == Taken -> Left "LockerNumber already taken!"
  | otherwise -> Right code
这也可以仅通过模式来表达:

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

回答得好!尤其是行
防护只是模式的约束