哈斯克尔 - 警惕案件陈述 [英] Haskell - guard inside case statement

查看:132
本文介绍了哈斯克尔 - 警惕案件陈述的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读学习你的haskell 书,并在第8章中有一段代码看起来像这样

  data LockerState = Taken |自由派生(Eq,Show)
类型代码=字符串
类型LockerMap = Map.Map Int(LockerState,Code)

lookup':: Int - > LockerMap - >无论是
lookup'num_map_ =
case(Map.lookup num_map_)
Nothing - >左$LockerNumber不存在!
Just(状态,代码) - >如果状态==采取
然后左$LockerNumber已经采取!
其他权利$ code

这有效。然而,我想转换if / else块来防止类似这样的语句:

pre code lookup':: Int - > LockerMap - >无论是
lookup'num_map_ =
case(Map.lookup num_map_)
Nothing - >左$LockerNumber不存在!
Just(状态,代码) - >
| state == Taken =离开$LockerNumber already taken!
|否则= Right $ Code

这不能编译。看起来,Haskell的守卫使用非常有限/非直观。 SO Ex1 SO Ex2 。有一个明确的来源,我可以阅读它告诉我可以在哪些地方使用警卫?

解决方案

有两个地方守卫是允许的:函数定义和 case 表达式。在这两种情况下,守卫在之前出现在之后,所以您在函数中使用 = ,在< c $ c $> - > 在 case 分支中,像往常一样:

 除以xy 
| y == 0 = Nothing
--------
|否则= Just(x / y)
-----------

positive mx = case mx of
只需x | x> 0 - >只需x
-------
_ - >没有什么

模式的守卫就是约束,所以 Just x 匹配任何非 - Nothing 值,但只需x | x> 0 只匹配 Just ,其包装值也为正数。



我想明确的参考文献是 Haskell Report ,具体来说就是&Sect; 3.13案例表达式和" 4.4.3函数和模式绑定(Pattern Bindings),它们描述了守卫的语法并指定了他们被允许的位置。



在你的代码中,你需要:

  Just(状态,代码)
|状态==采取 - >左已经取得LockerNumber!
|否则 - >正确的代码

这也可以单独表示:

  Just(Taken,_) - >左已经取得LockerNumber! 
Just(_,code) - >正确的代码


I am going through Learn you a haskell book, and in Chapter 8 there is a snippet of code which looks like this

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

This works. However, I wanted to convert if/else block to guard statements like this:

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

This doesn't compile. It seems that usage of guards in Haskell is very restrictive/non intuitive. SO Ex1 SO Ex2. Is there a definite source which I can read which tells at which places I can use guards?

解决方案

There are two places guards are allowed: function definitions and case expressions. In both contexts, guards appear after a pattern and before the body, so you use = in functions and -> in case branches, as usual:

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

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

Guards are simply constraints for patterns, so Just x matches any non-Nothing value, but Just x | x > 0 only matches a Just whose wrapped value is also positive.

I suppose the definitive reference is the Haskell Report, specifically §3.13 Case Expressions and §4.4.3 Function and Pattern Bindings, which describe the syntax of guards and specify where they’re allowed.

In your code, you want:

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

This is also expressible with patterns alone:

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

这篇关于哈斯克尔 - 警惕案件陈述的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆