【问题标题】:Haskell - guard inside case statementHaskell - 保护内部案例声明
【发布时间】:2017-04-11 16:45:40
【问题描述】:

我正在浏览Learn you a haskell 的书,在第 8 章中有一段类似这样的 sn-p 代码

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 Ex1SO Ex2。有没有我可以阅读的明确来源告诉我可以在哪些地方使用警卫?

【问题讨论】:

    标签: haskell pattern-guards


    【解决方案1】:

    有两个地方允许使用守卫:函数定义和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

    我想最终的参考是 Haskell Report,特别是 §3.13 Case Expressions 和 §4.4.3 Function and Pattern Bindings,它们描述了守卫的语法并指定了它们被允许的位置。

    在你的代码中,你想要:

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

    这也可以单独用模式来表达:

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

    【讨论】:

    • 很好的答案!尤其是Guards are simply constraints for patterns这一行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多