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