POV-Ray : Newsgroups : povray.off-topic : Assorted programming weirdness Server Time
6 Nov 2024 00:30:02 EST (-0500)
  Assorted programming weirdness (Message 1 to 1 of 1)  
From: Orchid XP v8
Subject: Assorted programming weirdness
Date: 18 Sep 2008 16:05:06
Message: <48d2b472@news.povray.org>
In C and C++, assignment is an operator. Which, obviously, is pretty weird.

However, Haskell can go one better than that. ;-)

I was just reading "Thinking in C++", and it started talking about how 
the assignment operator works. In particular, "x = 4" is a valid 
assignment, but "4 = x" is not. "Because, obviously, that would be 
pretty silly."

But in Haskell... actually *both* of those are perfectly legal. o_O

Consider, for example, the function

   foo x =
     let 4 = x
     in  2*x

Since the let-binding isn't "used" for anything, it actually has no 
effect (due to lazy evaluation). For a similar reason, if I transform 
this into a monadic function:

   foo x = do
     let 4 = x
     return (2*x)

then still it does nothing. (Again, it isn't "used" - nor is it possible 
to "use" it.)

However, if I insert this into the monadic binding sequence, thus 
forcing it to execute, something does happen:

   foo x = do
     4 <- return x
     return (2*x)

Exactly what happens here depends on which monad you use. (This function 
can be run in *any* monad.) If you run it in the IO monad, the following 
happens:

- "foo 4" will return the number "8".

- "foo 1" will throw an exception with a rather cryptic message.

If instead you run this inside the list monad, something slightly 
different occurs:

- "foo 4" will return a 1-element list that contains "8".

- "foo 1" will return an empty list.

So it seems that essentially we have just created a rather obfuscated 
way to check wether x = 4 or not! :-D

All of this works because in Haskell, the LHS of a definition is *not* 
required to be a variable - it is a *pattern*, and the definition causes 
the value produced by the RHS to be *pattern matched* against the LHS. I 
variable is a valid pattern, but so is "4".

To illustrate why the language is designed this way, consider

   let [x,y,z] = [1,2,3]

It should be relatively obvious what this does. (It says x=1, y=2 and 
z=3.) While this example is pretty pointless, it is however quite common 
to want to do something like

   let (list1, list2) = splitAt 5 my_list

where a function returns a pair of results and you want to assign each 
one to a different variable.

The reason the final version of foo does what it does is due to a subtle 
edge-case of the language. Firstly, pattern matching can fail. If you 
say "x = 3", this cannot possibly fail. However, if you say "[x,y,z] = 
[1,2]", the pattern match fails since the lists aren't the same size.

In a let-expression, a pattern match failure causes an exception to be 
thrown. However, in a monadic let-statement, it causes the "fail" method 
of the monad to be called. By default this also throws an exception, but 
it depends on the monad; it can be redefined to do something else. And 
that's exactly what the list monad does - it redefines "fail" to just 
return an empty list!

So there we are - wasn't that pointless? :-D

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

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