POV-Ray : Newsgroups : povray.off-topic : 80 / 20 rule : 80 / 20 rule Server Time
5 Jul 2024 09:04:40 EDT (-0400)
  80 / 20 rule  
From: Orchid Win7 v1
Date: 17 Oct 2015 08:45:44
Message: <562242f8$1@news.povray.org>
You remember the 80 / 20 rule, right?

No, not the rule that 80% of the population falls within 2 standard 
deviations of the mean; that one's actually baloney. It's only true *if* 
the data follows a normal distribution - which is by no means always 
true. And even then, it's 95.449%, not 80%. :-P

I'm talking about the rule that says that 80% of people only use 20% of 
the available functionality. Or that 20% of the development effort 
implements 80% of the functionality, and the last 80% of developer time 
is required to do that last 20% of functionality.



So I'm writing a Haskell parser. The vast majority of Haskell code uses 
very simple syntax. But it seems the language specification includes a 
huge amount of flexibility that hardly anybody uses. Today I've 
discovered things I didn't even know you could *do*!

For example, one way to do pattern matching in Haskell is with a case-block:

   case list of
     [x]       -> x
     [x, y]    -> x + y
     [x, y, z] -> x + y + z
     _         -> 0

This takes a list and adds its elements, unless there's more than three 
of them, in which case it returns 0. Simple enough, right? Well, you can 
also add "guards" to a pattern:

   case list of
     [x, y, z]
       | x <  0 -> ...
       | x >  0 -> ...
       | x == 0 -> ...

Well, it turns out you can have *multiple guards* on a single expression!

   case list of
     [x, y, z] | x > 0, y > 0, z > 0 -> ...

What does that even *do*?! <read the spec/> OK, so it seems it's the 
logical-AND of all the conditions? So, um, why not just write it as an AND?

But it's worse. Apparently you can write local declarations *inside* a 
guard. And the variables thus declared are in-scope for the rest of the 
line. Wuh?!

   case list of
     [x, y, z] | let w = x + y + z -> w

WHY WOULD YOU DO THIS?!

But wait, it's worse: you can put a pattern *inside* a pattern guard...

   case list of
     [x, y, z] | [a, b, c] <- x, [d, e, f] <- y, [g, h, i] <- z -> ...

This mind-bending snippet does precisely the same thing as

   case list of
     [[a, b, c], [d, e, f], [g, h, i]] -> ...

Except that the latter is actually *readable*. (It matches a 3-element 
list of 3-element lists.)

The only reason I can think of for this obscure feature is to allow 
somebody to do something like

   case mode of
     ModeX info | let sub = decrypt info, SubmodeXK <- sub -> ...

In other words, pattern match, run a function on the result, and pattern 
match again on the result of that. But, seriously, WHAT ARE YOU DOING 
WITH YOUR LIFE?! That is *way* too much crazy to try to squeeze into one 
equation. For the love of God, break that stuff into something smaller!

   case mode of
     ModeX info ->
       case decrypt info of
         SubmodeXK -> ...

There. That wasn't so hard, was it? :-P



Also slightly nauseating is that you're allowed to specify operator 
fixity declarations inside a local variable block. But I guess that's 
not really so bad; I suppose the *bad* thing is that you're allowed to 
declare local operators in the first place!

   let
     x # y = x * cos y
     infixl 7 #
   in 1 # 2 # 3

This declares a new "#" operator, which exists only inside this one code 
block, and has a precedence of 7 and is left-associative. If you were a 
really sick human being with serious mental problems, you could create a 
loop where an operator does something different on each pass through the 
loop.

Oh God, wait... You can do all of this *inside* a pattern guard!

   case list of
     [a, b, c] | let {x # y = x * cos y, infixl 7 #}, a # b # c > 0 -> 1

MY EYES!!! >_<


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.