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
inp
demanded, consider constructors in syntactic tree ofp
reachablex
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
ory
orys
,value
evaluated as needed matchy:ys
(and triple) - if demand
z
orw
orws
,value
evaluated as needed matchy: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
Post a Comment