[Haskell] insufficiently laziness@pattern -- more counterintuitive stuff
I would assume that this function: foo list@(h:t) = list is equivalent to foo list = list where (h:t)=list But passing [] to the first generates an error even though h and t are never used! Passing [] to the second works just fine. At this point, I sort of understand the reason for MR and not having partially applied type synonyms, but this seems entirely like an issue of syntactic sugar.... FYI, I encountered this issue attempting to write code that merges the content of two lists of tuples e.g. merge left@((xL,yL):restL) right@((xR,yR):restR) | left==[] = .... I imagine this issue is fairly common so perhaps its another idiom issue. -Alex- PS This code is part of a joinSets function for data.Sets _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com
tis 2004-03-30 klockan 17.30 skrev S. Alexander Jacobson:
I would assume that this function:
foo list@(h:t) = list
is equivalent to
foo list = list where (h:t)=list
But passing [] to the first generates an error even though h and t are never used! Passing [] to the second works just fine.
You can write this as
foo' list@(~(h:t)) = list
foo' [] will evaluate to []. The H98 report calls it an "irrefutable pattern", IIRC. Regards, Martin
Thanks for the ~ syntax, but my question is really why you need it? What benefit do you get from "refutable patterns"? Alternatively, would anything break if a future Haskell just treated all patterns as irrefutable? -Alex- _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com On Tue, 30 Mar 2004, Martin [ISO-8859-1] Sj�gren wrote:
tis 2004-03-30 klockan 17.30 skrev S. Alexander Jacobson:
I would assume that this function:
foo list@(h:t) = list
is equivalent to
foo list = list where (h:t)=list
But passing [] to the first generates an error even though h and t are never used! Passing [] to the second works just fine.
You can write this as
foo' list@(~(h:t)) = list
foo' [] will evaluate to []. The H98 report calls it an "irrefutable pattern", IIRC.
Regards, Martin
A lot. If everything were irrefutable, then the following:
mymap f (x:xs) = f x : xs mymap f [] = []
would never get to the second branch and would fail when it reached the end of a list. so would it if you put the lines in the other, "more natural," order, though perhaps it's less clear why. A lot of things would break if this were changed. Refutable patterns are definitely the norm, not the exception. On Tue, 30 Mar 2004, S. Alexander Jacobson wrote:
Thanks for the ~ syntax, but my question is really why you need it? What benefit do you get from "refutable patterns"?
Alternatively, would anything break if a future Haskell just treated all patterns as irrefutable?
-Alex-
_________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com
On Tue, 30 Mar 2004, Martin [ISO-8859-1] Sjögren wrote:
tis 2004-03-30 klockan 17.30 skrev S. Alexander Jacobson:
I would assume that this function:
foo list@(h:t) = list
is equivalent to
foo list = list where (h:t)=list
But passing [] to the first generates an error even though h and t are never used! Passing [] to the second works just fine.
You can write this as
foo' list@(~(h:t)) = list
foo' [] will evaluate to []. The H98 report calls it an "irrefutable pattern", IIRC.
Regards, Martin
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
-- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
On Tue, 2004-03-30 at 18:01, S. Alexander Jacobson wrote:
Thanks for the ~ syntax, but my question is really why you need it? What benefit do you get from "refutable patterns"?
Alternatively, would anything break if a future Haskell just treated all patterns as irrefutable?
A short pragmatic answer is that "refutable patterns" are stricter and so more efficient. (Oops, I've fallen into the C programmers trap of justifying things by efficiency first and thinking later) How about justifying it by saying that they translate directly into case expressions without any extra let, and so are easier to think about that way. Or finally, the "it's what you want most often" argument. For example out of the whole Prelude+List modules, the only functions that use irrefutable patterns are the unzip functions. Duncan
G'day all. Quoting Duncan Coutts <duncan@coutts.uklinux.net>:
Or finally, the "it's what you want most often" argument.
How about the "it's the most natural thing" argument? Pattern matching on the LHS of a function definitions looks, for all the world, like a set of rewrite rules. That's because, in some sense, they are. In this definition: f (x:xs) = 1 + f xs f [] = [] Intuitively, the first rule should only "fire" if the expression being evaluated conforms to the left-hand side. A google search for "conformality check" may also help. A potentially frightening thought is that something like the above definition would make sense in a lazy _logic_ language. Cheers, Andrew Bromage
Andrew Bromage:
Pattern matching on the LHS of a function definitions looks, for all the world, like a set of rewrite rules. That's because, in some sense, they are.
In this definition:
f (x:xs) = 1 + f xs f [] = []
Intuitively, the first rule should only "fire" if the expression being evaluated conforms to the left-hand side.
But beware that even though they can be seen as rewrite rules, there is a difference in that a term rewrite system allows all possible orders of applying rewrite rules, whereas Haskell specifies a top-down order in which the rules are tried. This can make a difference if patterns overlap, so several patterns can match a given argument. In the given example the patterns do not overlap though, so this can indeed be seen as a little term rewriting system defining f. Björn Lisper
"aj" == S Alexander Jacobson <alex@alexjacobson.com> writes:
aj> I would assume that this function: aj> foo list@(h:t) = list aj> is equivalent to aj> foo list = list aj> where (h:t)=list aj> But passing [] to the first generates an error aj> even though h and t are never used! Passing [] to aj> the second works just fine. The @-pattern behaves exactly as specified in the Haskell report under "3.17.2 Informal Semantics of Pattern Matching": 9. Matching an as-pattern var@apat against a value v is the result of matching apat against v, augmented with the binding of var to v. If the match of apat against v fails or diverges, then so does the overall match. And the following translation is suggested in the preceding section: Patterns of the form var@pat are called as-patterns, and allow one to use var as a name for the value being matched by pat. For example, case e of { xs@(x:rest) -> if x==0 then rest else xs } is equivalent to: let { xs = e } in case xs of { (x:rest) -> if x==0 then rest else xs } -Peter
participants (8)
-
ajb@spamcop.net -
Bjorn Lisper -
Duncan Coutts -
Hal Daume III -
Martin Sjögren -
Peter Thiemann -
S. Alexander Jacobson -
S. Alexander Jacobson