Removal candidates in patterns

I am very please to see on the Wiki also a list of removal candidates and that these include n+k patterns and ~ patterns. I'd like to add one pattern to this list of removal candiates: k patterns, that is, numeric literals. Why do I want to get rid of these three patterns? Because all three caused me no end of trouble when implementing the program transformation of the Haskell tracer Hat. Hat actually still doesn't handle nested ~ patterns. Why are these patterns so hard to implement for Hat? Surely the Haskell report gives a translation into simple core Haskell. Well, Hat does not use this translation because it does not want to be an inefficient pattern matcher (leave that job to the compiler) but produce a trace of the Haskell program as it is written. However, both n+k and k patterns cause calls of functions ( (-), (==) etc) that Hat has to record in its trace. Also ~ patterns do not fit the simple rewriting semantics of the Hat trace and hence have to be recorded specially. While in simple cases that occur in practice it is pretty straightforward to remove n+k, k and ~ patterns from a larger pattern while keeping the rest of the larger pattern intact, in the general case this is incredibly hard. Iff n+k patterns are removed, there is little good use for k patterns either. Since the introduction of monadic IO the ~ pattern is hardly used in practice either. In all the simple cases that these three are currently used in practice, it is easy for the programmer to define their function in an alternative way. So get rid of these three and pattern matching becomes so much more simple. Ciao, Olaf

On 2006-01-26, Olaf Chitil
I am very please to see on the Wiki also a list of removal candidates and that these include n+k patterns and ~ patterns.
I'd like to add one pattern to this list of removal candiates: k patterns, that is, numeric literals.
I don't see that much use for the first two but I really want to argue for being able to pattern-match on numeric literals. I think numeric literals should be treated as much as possible as if there were declarations like "data Int = 0 | 1 | (-1) | 2 | (-2) | ..." Or am I misunderstanding the suggestion here?
Iff n+k patterns are removed, there is little good use for k patterns either.
Say what? n+k could perhaps serve some pedagogical purpose in presenting the peano numbers. Plain old literals are not so tied to a particular representation (that is, you can imagine 4 being expanded to match Int# 4, or BooleanSequence [T,F,F] internally, or whatever and still looking exactly the same in the code), and have the same utility as being able to pattern-match any data.
So get rid of these three and pattern matching becomes so much more simple.
From the point of view of Hat, yes. Despite how useful hat is, I'd rather have the ability to do
ack 0 n = n+1 ack m 0 = ack (m-1) 1 ack m n = ack (m-1) (ack m (n-1)) which looks far nicer than ack m n | m == 0 = n + 1 | n == 0 = ack (m-1) 1 | otherwise = ack (m-1) (ack m (n-1)) I admit this is 99% aesthetics, but aesthetics do matter, as does consistency and regularity. And there are some cases where the guards can get quite complex, especially when rewriting something that already combines pattern-matching with guards. -- Aaron Denney -><-

On Thu, 2006-01-26 at 17:01 +0000, Olaf Chitil wrote:
Why are these patterns so hard to implement for Hat? Surely the Haskell report gives a translation into simple core Haskell. Well, Hat does not use this translation because it does not want to be an inefficient pattern matcher (leave that job to the compiler) but produce a trace of the Haskell program as it is written. However, both n+k and k patterns cause calls of functions ( (-), (==) etc) that Hat has to record in its trace.
Does it not have to do that for character and string patterns too? I suppose that the proposals to create a string class and have string/character constants overloaded by that class would cause similar problems for Hat. Duncan

Olaf Chitil wrote:
I'd like to add one pattern to this list of removal candiates: k patterns, that is, numeric literals.
Wow! That's a mighty big thing to remove. For me personally that would cause endless trouble. I use k patterns all the time. (I'm happy to to see 'n+k' gone, because I never use them.) I don't even know how I'd try to motivate why they were removed to a casual Haskell user. "Some implementor was having trouble with k patterns in some tool so they are gone now"? Huh? Let's remove higher order functions too, they are tricky to implement. :) -- Lennart

Olaf Chitil wrote:
I'd like to add one pattern to this list of removal candiates: k patterns, that is, numeric literals.
I was rather shocked when I first read this. And I certainly don't like the argument from implementation difficulties in a certain tool!-) I don't mind losing (n+k), not because it wasn't neat, but it looks like a special case needing a more general solution, beyond Haskell''s scope. I don't want to lose numeric literals in patterns! But, having recovered from the first shock, and ignoring other people's hats, there may be a few things that need cleaning up in that area (why do some patterns work without Eq, some with? Should there be a Match class or something to pin down what can and what can't be matched how?..).
Let's remove higher order functions too, they are tricky to implement. :)
it seems so, at least for pattern matching "numeric literals"; what is the result of (f 1) and (g A) in the following code? ... -- some code omitted here f 1 = True f n = False g A = True g n = False and should it depend on the context (types, instances, ..), or not? run the following through ghci with and without the signature for f, and with either version of (==) for functions; and what happens if we uncomment the Eq instance for D? is that all as expected? cheers, claus --------------------------------------------------- module K where import Text.Show.Functions instance Eq (a->b) where f == g = False -- f == g = True instance Num b => Num (a->b) where fromInteger n = const $ fromInteger n -- f :: Num b => (a->b) -> Bool f 1 = True f n = False main = print $ (f 1,g A) ------------- data D = A | B -- no Eq, but matching allowed -- instance Eq D where a == b = False g A = True g n = False

Hello Claus, Friday, January 27, 2006, 3:51:26 AM, you wrote: CR> I don't want to lose numeric literals in patterns! But, having recovered CR> from the first shock, and ignoring other people's hats, there may be a CR> few things that need cleaning up in that area (why do some patterns CR> work without Eq, some with? Should there be a Match class or CR> something to pin down what can and what can't be matched how?..). this makes sense for me. Ruby has the special class for matching, so that something like case x of "str" -> 1 1.1 -> 2 /regexp/ -> 3 translated into the if x =~ "str" then 1 else if x =~ 1.1 then 2 else if x =~ /regexp/ then 3 that allows to define matching rules by writing appropriate definitions for "=~" -- Best regards, Bulat mailto:bulatz@HotPOP.com
participants (6)
-
Aaron Denney
-
Bulat Ziganshin
-
Claus Reinke
-
Duncan Coutts
-
Lennart Augustsson
-
Olaf Chitil