Haskell AS在不可辩驳的模式上进行绑定

加布里埃尔·丘博塔鲁(Gabriel Ciubotaru)

我正在尝试将不可辩驳的模式和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匹配所有内容
  • 如果需要xin变量p则考虑语法树中的pfrom的所有构造函数,x除了在a上向下移动~:匹配的值将被评估为与这些构造函数匹配
  • 如果以上匹配失败,请引发异常

例子:

case value of ~(x,y:ys,~(z,w:ws)) -> ...
  • 如果我们不要求任何东西,那么value将不会被评估
  • 如果我们要求xyys,则将value根据需要进行尽可能多的匹配y:ys(和三重匹配评估
  • 如果我们要求zor或wor ws,那么value将根据需要匹配y:ysw: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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章