Haskell AS binding on irrefutable pattern -


i'm trying use both irrefutable pattern , bindings function evaluate reverse polish notation expression.

here code:

resolverpn :: string -> [integer] resolverpn = foldl helper [] . words               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             

basically irrefutable fail if give list less 2 elements should used "+-*/". if function applied "10 10" should use "otherwise" , use binding "stack" , should not try break constructos, seems doesn't work that.

if instance fold helper , use [0,0] accumulator, everithing works fine if there no need of values.

can explain why code still raise "irrefutable pattern" excepton ? or how haskell evaluate ?

here simplified code :

notworking :: [int] notworking = helper [] "10"                       helper ~stack@(x1:x2:xs) el = (read el) : stack    working:: [int] working = helper [] "10"               helper ~stack el = (read el) : stack   

the thumb rule is:

  • an irrefutable/lazy pattern ~p matches everything
  • if variable x in p demanded, consider constructors in syntactic tree of p reachable x except moving downwards across ~: value being matched evaluated match these constructors
  • if match above fails, raise exception

example:

case value of ~(x,y:ys,~(z,w:ws)) -> ... 
  • if not demand anything, value not evaluated
  • if demand x or y or ys, value evaluated as needed match y:ys (and triple)
  • if demand z or w or ws, value evaluated as needed match y:ys , w:ws (and triple , pair)

tests:

> 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 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 pattern (x, y : ys, ~(z, w : ws)) > case (3,[0],(4,[])) of ~(x,y:ys,~(z,w:ws)) -> z *** exception: irrefutable pattern failed pattern (z, w : ws) 

in opinion, semantic nicer if every subpattern under ~ behaved if had ~ above it. e.g. if ~(x,y:ys) equivalent ~(x,~(y:ys)). current semantics allow more flexibility, though.


the rule holds in presence of "as" patterns. instance, in

case value of a@ ~(x,y:ys,~b@(z,c@(w:ws))) -> ... 

demanding a not evaluate value demanding other variable cause value evaluated match triple. further, demanding of x,y,ys cause evaluation match list constructor in y:ys. instead, matching b or of z,c,w,ws cause value evaluated further, match pair (z,c@(w:ws)) list w:ws, under second ~.

--here example "as" pattern outside succeed > case (1,[],(2,[3])) of a@ ~(x,y:ys,~b@(z,c@(w:ws))) -> (1,[],(2,[3]))  --this fail because triple y:ys evaluated along > case (1,[],(2,[3])) of ~a@(x,y:ys,~b@(z,c@(w:ws))) -> *** exception: irrefutable pattern failed pattern a@(x, y : ys, ~b@(z, c@(w : ws))) 

in code can put "as" binding outside ~ this:

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  

and work fine valid rpn input.


Comments