我正在尝试将不可辩驳的模式和AS绑定都用于评估反向波兰表示法表达式的函数中。
这是我的代码:
resolveRPN :: String -> [Integer]
resolveRPN = foldl helper [] . words
where
helper ~stack@(x1:x2:xs) el
| el == "+" = (x2 + x1) : xs
| el == "-" = (x2 - x1) : xs
| el == "*" = (x2 * x1) : xs
| el == "/" = (x2 `div` x1) : xs
| otherwise = (read el) : stack
基本上,如果您给出的列表少于2个元素,则不可辩驳的操作将失败,但这仅应用于“ +-* /”。如果将函数应用于“ 10 10”,则应仅使用“否则”并使用AS绑定“堆栈”,并且不应尝试将其分解为constructos,但似乎无法正常工作。
例如,如果我折叠助手,并使用[0,0]作为累加器,即使不需要此值,一切都可以正常工作。
有人可以解释为什么此代码除了还会引发“不可辩驳的模式”吗?还是Haskell如何评价这一点?
这是简化的代码:
notWorking :: [Int]
notWorking = helper [] "10"
where
helper ~stack@(x1:x2:xs) el = (read el) : stack
working:: [Int]
working = helper [] "10"
where
helper ~stack el = (read el) : stack
经验法则是:
~p
匹配所有内容x
in变量,p
则考虑语法树中的p
from的所有构造函数,x
除了在a上向下移动~
:匹配的值将被评估为与这些构造函数匹配例子:
case value of ~(x,y:ys,~(z,w:ws)) -> ...
value
将不会被评估x
或y
或ys
,则将value
根据需要进行尽可能多的匹配y:ys
(和三重匹配)评估z
or或w
or ws
,那么value
将根据需要匹配y:ys
和w:ws
(以及三元组和货币对)进行尽可能多的评估测试:
> case undefined of ~(x,y:ys,~(z,w:ws)) -> "hello"
"hello"
> case (3,undefined,(4,[1])) of ~(x,y:ys,~(z,w:ws)) -> x
*** Exception: Prelude.undefined
> case (3,[],(4,[1])) of ~(x,y:ys,~(z,w:ws)) -> x
*** Exception: Irrefutable pattern failed for pattern (x, y : ys, ~(z, w : ws))
> case (3,[0],(4,undefined)) of ~(x,y:ys,~(z,w:ws)) -> x
3
> case (3,[0],(4,[])) of ~(x,y:ys,~(z,w:ws)) -> x
3
> case (3,[],(4,[1])) of ~(x,y:ys,~(z,w:ws)) -> z
*** Exception: Irrefutable pattern failed for pattern (x, y : ys, ~(z, w : ws))
> case (3,[0],(4,[])) of ~(x,y:ys,~(z,w:ws)) -> z
*** Exception: Irrefutable pattern failed for pattern (z, w : ws)
我认为,如果一个~
行为下的每个子模式都表现得好于其~
上方,那么语义可能会更好。例如是否~(x,y:ys)
等于~(x,~(y:ys))
。但是,当前的语义确实允许更大的灵活性。
该规则即使在存在“ as”模式的情况下也成立。例如,在
case value of a@ ~(x,y:ys,~b@(z,c@(w:ws))) -> ...
要求a
不会评估,value
但要求其他任何变量将导致value
要评估,以便与三元组匹配。此外,要求其中的任何一个x,y,ys
也会导致求值结果与中的列表构造函数匹配y:ys
。取而代之的是,匹配项b
或匹配项中的任何一个z,c,w,ws
都将导致value
进一步评估,因此要匹配第二个对(z,c@(w:ws))
和列表w:ws
对~
。
--Here is an example with "as" pattern outside that will succeed
> case (1,[],(2,[3])) of a@ ~(x,y:ys,~b@(z,c@(w:ws))) -> a
(1,[],(2,[3]))
--This will fail because the triple as well as y:ys will be evaluated along a
> case (1,[],(2,[3])) of ~a@(x,y:ys,~b@(z,c@(w:ws))) -> a
*** Exception: Irrefutable pattern failed for pattern a@(x, y : ys, ~b@(z, c@(w : ws)))
在您的代码中,您可以简单地将“ as”绑定放在~
如下所示的外部:
helper stack@ ~(x1:x2:xs) el
| el == "+" = (x2 + x1) : xs
| el == "-" = (x2 - x1) : xs
| el == "*" = (x2 * x1) : xs
| el == "/" = (x2 `div` x1) : xs
| otherwise = (read el) : stack
并适用于任何有效的RPN输入。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句