POV-Ray : Newsgroups : povray.off-topic : I found this interesting : Re: [Caution: long monad ramble] Server Time
1 Oct 2024 15:23:04 EDT (-0400)
  Re: [Caution: long monad ramble]  
From: Orchid XP v8
Date: 11 Apr 2008 14:46:50
Message: <47ffb21a$1@news.povray.org>
>> Consider the Maybe monad. It's useful for functions that might fail. 
>> For example,
>>
>>   solve :: Double -> Double -> Maybe Double
>>   solve a b = if a == 0 then Nothing else Just ((0 - b)/a)
> 
> 
> solve(A,B) when A == 0 -> nothing;
> solve(A,B) -> ((0-B)/A).
> 
> (Note that "nothing" here is just an "atom", i.e., an interned string, a 
> LISP "symbol", a Smalltalk "symbol", etc. It's not a special value or 
> type. Just something you can match on later.)

Heh. I remember using symbols in Smalltalk. Just for the love of God, 
don't try to mutate them...!

>>   (Just x)  >>= f = f x
>>   (Nothing) >>= f = Nothing
> 
> do_maybe(Fun, X) when X == nothing -> nothing;
> do_maybe(Fun, X) -> Fun(X).
> 
> Probably not equivalent in a deeper sense.

No, that's more or less exactly it. Oh, except that "f" is type 
constrained to *also* return a Maybe value. (But not necessarily 
containing the same type of data.)

> But you're giving me some ideas for some higher-order functions I 
> probably need. I still miss "while" loops, but I've been trying to 
> figure out how to make while() into a function that takes two lambdas. :-)

Well now, doesn't that rather depend on what this loop is supposed to 
*do*? ;-) In Haskell, we have several different while loops, all for 
different jobs.

There's takeWhile, dropWhile and span which chop up segments of lists. 
There's "unfoldr" which builds lists. There's "until", which repeats a 
computation until a condition holds, and returns the final result. And 
so on...

>>   factors k = do
>>     x <- [1..10]
>>     y <- [1..10]
>>     if x * y == k then [(x,y)] else []
> 
> In Erlang:
> factors(K) ->
>   Seq = lists:seq(1,K),
>   [ X*Y || X <- Seq, Y <- Seq, X * Y == K ].

Like I said, Haskell also possesses list comprehensions, and they are 
intimately related to monadic expressions. In Haskell, one could write

   [ x*y | x <- seq, y <- seq, x * y == k ]

Interestingly, Haskell possesses a "guard" function:

   guard (x*y == k)
   return (x,y)

If the condition fails, guard aborts the rest. Otherwise it continues. 
Similarly "when" runs or doesn't run just one part of a computation.

I should perhaps also mention "return" and "fail" somewhere. All monads 
have a "return" method that inserts a single element into the monad:

   return 5 >>= print

is the same as just "print 5". The "fail" method takes a text message 
and aborts the computation. For Maybe or lists, the message is ignored, 
but for the IO monad it throws an exception. There are monads that allow 
you to actually *use* the description for something useful. It's 
basically so that pattern match failures inside a monad trigger the 
monad's error-handling abilities rather than throw an exception...

> Thanks for the explanation. I'm still not 100% sure what the "value" in 
> the monad returned by getclock looks like, tho. I know it's supposed to 
> be opaque, but what in theory is in there, could you say?

Theoretically, you might have something like

   data IO x =
     CMD_GET_CHAR Handle |
     CMD_PUT_CHAR Handle |
     CMD_TEST_EOF Handle |
     ...
     CMD_GET_CLOCK_TIME |
     ...

But in reality, I believe GHC actually implements it as a structure 
holding a raw pointer to a C function that actually does the work. Note 
that it's 100% compiler-specific how IO is actually implemented though. 
It's completely outside the language spec... ;-)

So, when you hold an "IO Int", you're probably just holding a pointer to 
a C function which, when executed, is going to return an integer.

> Wow. You have your own newsgroup. :-)

Where *have* you been dear boy? ;-)

> I'll take a look.

TY.

-- 
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.