POV-Ray : Newsgroups : povray.off-topic : I found this interesting : Re: [Caution: long monad ramble] Server Time
1 Oct 2024 15:19:13 EDT (-0400)
  Re: [Caution: long monad ramble]  
From: Darren New
Date: 11 Apr 2008 12:12:46
Message: <47ff8dfe$1@news.povray.org>
Invisible wrote:
> It does those things in the order given. If you assign a result to a 
> variable, that result stays the same thereafter.

OK. Same as Erlang. :-)

> And you can do
> 
>   do
>     foo
>     let x = print "hello"
>     bar
>     x
> 
> which will print "hello" immediately after performing "bar". Nothing 
> hard here. ;-)

Same as Erlang, except you'd have to make it explicitly a fun (aka lambda).

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

> So you see that ">>=" takes a Maybe and a function that returns a Maybe, 
> and... well, let me just write the code, it's faster:
> 
>   (Just x)  >>= f = f x
>   (Nothing) >>= f = Nothing
 >
> So when you do "solve j k >>= f", if solve returns Nothing, just skip f 
> completely and return Nothing directly. Otherwise, take whatever data 
> came from solve, fish it out of the Maybe value, and feed it to f.

do_maybe(Fun, X) when X == nothing -> nothing;
do_maybe(Fun, X) -> Fun(X).

Probably not equivalent in a deeper sense.

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

> In other words, we can now have a chain of actions where a single 
> failure triggers an escape from the whole sequence - but doesn't clutter 
> up the logic of the program on paper.

Yep.

> Now we can do exactly the same thing with lists. If you think about it, 
> a Maybe stores either 0 or 1 results. Well, a list can store 0 or 1 or 2 
> or 3 or...
> 
>   xs >>= f = concat (map f xs)
> 
> As should be clear, if xs is the empty list, f is never run at all, and 
> you just get an empty list as the result. This is like the Maybe case. 
> Assuming xs is a nonempty list, run f for every element in xs and merge 
> the results.
> 
> It gets slightly confusing when you start using do-notation, but it's 
> quite powerful:
> 
>   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 ].


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?

> PS. If you've got a moment, there's a Tcl implementation of my logic 
> solver over in the povray.off-topic.haskell. I'd be interested to know 
> if you can make it any less... butt-ugly, for want of a better word!

Wow. You have your own newsgroup. :-)

I'll take a look.

-- 
   Darren New / San Diego, CA, USA (PST)
     "That's pretty. Where's that?"
          "It's the Age of Channelwood."
     "We should go there on vacation some time."


Post a reply to this message

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