skg*_*nga 19 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_ map_) of
Nothing -> Left $ "LockerNumber doesn't exist!"
Just (state, code) -> if state == Taken
then Left $ "LockerNumber already taken!"
else Right $ code
Run Code Online (Sandbox Code Playgroud)
这有效.但是,我想将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
Run Code Online (Sandbox Code Playgroud)
这不编译.似乎在Haskell中使用防护是非常严格/非直观的.SO Ex1 SO Ex2.是否有一个明确的来源,我可以阅读,告诉我哪些地方我可以使用警卫?
Jon*_*rdy 47
允许使用两个防护:功能定义和case表达式.在两种情况下,后卫出现后一种模式和之前的身体,让你使用=的功能和->在case树枝,像往常一样:
divide x y
| y == 0 = Nothing
--------
| otherwise = Just (x / y)
-----------
positively mx = case mx of
Just x | x > 0 -> Just x
-------
_ -> Nothing
Run Code Online (Sandbox Code Playgroud)
防护只是模式的约束,因此Just x匹配任何非Nothing值,但Just x | x > 0只匹配Just其包装值也是正值的.
我认为最终的引用是Haskell报告,特别是§3.13案例表达式和§4.4.3函数和模式绑定,它们描述了守卫的语法并指定了它们被允许的位置.
在您的代码中,您需要:
Just (state, code)
| state == Taken -> Left "LockerNumber already taken!"
| otherwise -> Right code
Run Code Online (Sandbox Code Playgroud)
仅使用模式也可以表达这一点:
Just (Taken, _) -> Left "LockerNumber already taken!"
Just (_, code) -> Right code
Run Code Online (Sandbox Code Playgroud)