Re: interesting example of lazyness/ghc optimisation
There's something that I've been wanting to ask sombody about, since it isn't terribly clear to me. Blatantly hijacking a function from Julian's code:
runRandom last max num | num > 1 = runRandom (fst new) max (num-1) | otherwise = snd new
While ifs are perhaps more intuitive when there are only two choices (like here!), and pattern matching matches on the type of arguments and not (only) their values, What's the difference between the pipe-syntax, and a case statement, i.e. writing the function as runRandom last max num = case num of 1 -> runRandom .... otherwise -> snd new Is there a practical difference, and if not, why are there two ways to skin this particular cat? Apologies for coming up with a terribly naive question, but I've looked in the HR without gaining much wisdom (beyond the recipe for translating if to case). -kzm -- If I haven't seen further, it is by standing in the footprints of giants
* * * Ketil Malde <ketil@ii.uib.no> wrote:
runRandom last max num | num > 1 = runRandom (fst new) max (num-1) | otherwise = snd new
What's the difference between the pipe-syntax, and a case statement, i.e. writing the function as
runRandom last max num = case num of 1 -> runRandom .... otherwise -> snd new
There is no difference. The 'pipe-syntax' (or pattern guards) gets desugared (by the pattern matching compiler) to case statements i.e.: runRandom = \ last max num.case (num > 1) of True -> runRandom (fst new) max (num-1) False -> snd new For a more detailed discussion see SPJ's book, Augustsson original paper, or M Pettersen't thesis (LNCS 1549). HTH, --laszlo
runRandom last max num | num > 1 = runRandom (fst new) max (num-1) | otherwise = snd new
What's the difference between the pipe-syntax, and a case statement, i.e. writing the function as
runRandom last max num = case num of 1 -> runRandom .... otherwise -> snd new
Eeek! This is not the same function! (num>1) =/= (num==1) Oh, and it isn't type-correct either. Try: runRandom last max num = case num>1 of True -> runRandom .... otherwise -> snd new Oops. No. Try again: runRandom last max num = case num>1 of True -> runRandom .... False -> snd new That's better. These transformations by hand can be tricky, huh? Regards, Malcolm
Ketil Malde wrote:
There's something that I've been wanting to ask sombody about, since it isn't terribly clear to me. Blatantly hijacking a function from Julian's code:
runRandom last max num | num > 1 = runRandom (fst new) max (num-1) | otherwise = snd new
While ifs are perhaps more intuitive when there are only two choices (like here!), and pattern matching matches on the type of arguments and not (only) their values,
What's the difference between the pipe-syntax, and a case statement, i.e. writing the function as
runRandom last max num = case num of 1 -> runRandom .... otherwise -> snd new
Is there a practical difference, and if not, why are there two ways to skin this particular cat?
You shouldn't compare case expressions with guards. Guards are used together with patterns, while case expressions are using patterns. Hence, it is possible to use guards in case expressions. The question is why *patterns* are allowed with function definitions. I guess the answer is syntax sugar. example: f [a] | a>0 = 1 | a<0 = 2 f _ = 3 -- [], [0], [a:as] Can be written as: f x = case x of [a] | a>0 -> 1 | a<0 -> 2 _ -> 3 -- Christian Brolin
participants (4)
-
Christian Brolin -
Ketil Malde -
Laszlo Nemeth -
Malcolm Wallace