繁体   English   中英

Haskell - 守卫案件陈述

[英]Haskell - guard inside case statement

我正在通过了解你是一本哈斯克书,在第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中使用防护是非常严格/非直观的。 SO Ex1 SO Ex2 是否有一个明确的来源,我可以阅读,告诉我哪些地方我可以使用警卫?

允许使用两个防护:功能定义和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 x匹配任何非Nothing值,但Just x | x > 0 Just x | x > 0仅匹配其包装值也为正的Just

我认为最终的引用是Haskell报告 ,特别是§3.13案例表达式和§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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM