POV-Ray : Newsgroups : povray.off-topic : I'm in the mood for monads Server Time
29 Jul 2024 10:30:27 EDT (-0400)
  I'm in the mood for monads (Message 21 to 30 of 93)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Orchid Win7 v1
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 11:34:18
Message: <4f9424fa$1@news.povray.org>
On 22/04/2012 05:33 AM, Shay wrote:
> On Sat, 21 Apr 2012 16:18:46 -0500, Orchid Win7 v1 <voi### [at] devnull> wrote:
>
>>
>> 1. You can take a 5-argument function, pass it 2 argument, and get a
>> 3-argument function as the result.
>>
>> Examples:
>>
>> - (+1) takes a number and adds one to it.
>>
>> - (5 ==) takes a number and returns True if it's 5.
>>
>> - "map" takes a function and a list. "map abs" takes a list of numbers
>> and returns a list of positive numbers.
>
> I think I understand monads—I'll likely never try Haskell to find out
> for sure.
> I'm pretty sure I understand currying—at least as far as it goes in Python.
>
> But I don't understand how any of these are taking a 5 argument
> function, passing it 2 arguments, and getting a 3 argument function as a
> result.

I couldn't find an example of a 5-argument function to demonstrate with. 
Generally, if you find yourself writing a function with that many 
arguments, you're doing it wrong.

So instead, I demonstrated with a couple of 2-argument functions 
generating 1-argument functions.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 11:40:36
Message: <4f942674$1@news.povray.org>
On 22/04/2012 11:40 AM, Warp wrote:

>    But that's the thing: It sounds so trivial as to defy sense. Why give
> a particular name to such a trivial thing?

One could argue that "calling a function" is a pretty trivial idea. But 
it's still useful to have a name for it.

>    But then when one starts asking questions like "so it's like giving
> default values to function parameters?" or "so it's like writing another
> function with less parameters that calls the first function by giving it
> some default values as the rest of the parameters?", the answer is something
> like "not really".

Providing default arguments is /kind of/ similar. The difference is that 
usually you /can/ still provide explicit values which override the 
defaults. With a curried function, you /cannot/ change the arguments 
that have already been given. (Or even know if any arguments /have/ been 
give yet. All you can see is what arguments remain.)

Writing a new function that takes one fewer arguments than an existing 
one is like currying. Except that the idea behind "currying" is that 
this is /automatic/. You don't have to code it yourself. It's 
automatically available for all functions.

Finally, like I said, currying works backwards too: If a function call 
happens to return a function as its result, you can just keep appending 
arguments. "head function_list 7" and all that.

Curried functions mean that, at the language level, there is 
fundamentally no difference between taking several arguments, and 
functions that return functions that return functions.

As you say, it's /not/ an especially wild concept. But it's [usually] 
not a feature that you can add without changing the language design.

That said, you could probably design some sort of object that has 
methods for adding arguments, N at a time, and when it gets enough 
arguments, it yields an answer. And that might reasonably be described 
as currying.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Living in a box
Date: 22 Apr 2012 11:48:08
Message: <4f942838$1@news.povray.org>
On 21/04/2012 10:53 PM, Le_Forgeron wrote:
> Le 21/04/2012 23:37, Orchid Win7 v1 nous fit lire :
>> "override operator;".
>
> For once, I'm glad C++ does not allow such!

Well, you'll notice that Haskell only does all this magical stuff IF YOU 
EXPLICITLY REQUEST IT. So any block of monadic code either has a big 
"do" right at the front of it, or all the ">>=" calls are written 
explicitly. Either way, it's pretty obvious that "hey man, something 
weird is going to happen here".

Haskell allows you to override many, many things: You can change what 
number literals mean. You can change what string literals mean. 
Obviously you can change what the various comparison and arithmetic 
operators do. Monad in a sense allow you to override the semicolon 
operator. You can even override pattern matching. But you know what? It 
/doesn't/ let you override function call syntax.

> The overloading (?) of<<  and>>  is already enough trauma when dealing
> with streams... or not.

You know, considering that C++ demands an explicit type signature on 
every tiny little thing... I'm having a hard time imagining how this 
would ever be a problem. Especially given that the argument to << is 
very, very likely to consist of at least one literal value.

> in fact, monade seems to be the<<  with polymorphic type added.

There is a (<<) function in Haskell, in fact, and yes, it's to do with 
monads. (It's the same as (>>), but with the arguments swapped around.)

> I wonder if there is a deep difference between haskell&  forth... or a
> bit of lisp. Just that haskell dropped all ()...

Haskell dropped the brackets because

1. Functions are first-class, so a "named function" is merely an 
ordinary variable who's "value" happens to be a function. So 
distinguishing between foo and foo() is not needed.

2. Functions are curried, so foo(1, 2, 3) might run the function and 
yield a result, or it might just yield a new, smaller function.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Living in a box
Date: 22 Apr 2012 11:49:56
Message: <4f9428a4$1@news.povray.org>
On 22/04/2012 11:59 AM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>> Further, let's pretend that you can create an anonymous function just by
>> writing
>
>>     int function(int x) {return 2*x;}
>
>    You can create anonymous functions. The syntax is:
>
>      [](int x) { return 2*x; }
>
>    (Of course that alone won't do anything because you can't call it, as
> it has no name. However, you can eg. create a variable that represents
> the function, like: "auto func = [](int x) { return 2*x; };". If you need
> to eg. return that function from another function, you'll have to use the
> std::function wrapper. Likewise if you need to give one as parameter to
> a non-templated or anonymous function.)

Mmm, interesting.

So how do you call such a function? Does it just override the usual 
function call notation?


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 11:54:37
Message: <4f9429bd$1@news.povray.org>
>> Heh, man... I thought "it inserts user-defined code between each pair of
>> statements" would a pretty simple idea. I guess not... ;-)
>
> I should have said that I am none the wiser. I still do not know what a
> monad is.

If you have a set of things which can be "added" and "subtracted" in a 
certain technical sense, this is called a monoid.

(The technical rules say things like "if you add X and Y, and then 
subtract Y, the result has to be X". Stuff like that.)



A monad is a little more complicated, but essentially, if you have

- A "box" type of some sort.

- A "return" function that takes a value and sticks it in a box.

- A "bind" function that takes a box and a function that returns a box, 
and calls that function with the thing(s) in the input box.

then that's a monad.

(Once again, there's a bunch of technical rules that make this 
mathematically rigorous. Technically the functions have to obey certain 
rules - the "monad laws" - such as "bind x id == x". But usually any 
sane way of implementing the two functions about will satisfy the 
requirements.)


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 11:56:52
Message: <4f942a44$1@news.povray.org>
On 22/04/2012 01:43 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>> 1. You can take a 5-argument function, pass it 2 argument, and get a
>> 3-argument function as the result.
>
>    Would this be currying in C++?
>
>      std::function<int(int)>  multiplierFunction(int multiplier)
>      {
>          return [multiplier](int value) { return value * multiplier; };
>      }
>
>    The above function returns a function that takes an integral as parameter
> and returns it multiplied by the specified multiplier.

Yeah, I think that would satisfy my idea of "curried function".

The question is, does

   multiplierFunction(3)(4)

or similar yield a 12?


Post a reply to this message

From: clipka
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 12:34:40
Message: <4f943320@news.povray.org>
Am 22.04.2012 17:40, schrieb Orchid Win7 v1:
> On 22/04/2012 11:40 AM, Warp wrote:
>
>> But that's the thing: It sounds so trivial as to defy sense. Why give
>> a particular name to such a trivial thing?
>
> One could argue that "calling a function" is a pretty trivial idea. But
> it's still useful to have a name for it.
>
>> But then when one starts asking questions like "so it's like giving
>> default values to function parameters?" or "so it's like writing another
>> function with less parameters that calls the first function by giving it
>> some default values as the rest of the parameters?", the answer is
>> something
>> like "not really".
>
> Providing default arguments is /kind of/ similar. The difference is that
> usually you /can/ still provide explicit values which override the
> defaults. With a curried function, you /cannot/ change the arguments
> that have already been given. (Or even know if any arguments /have/ been
> give yet. All you can see is what arguments remain.)
>
> Writing a new function that takes one fewer arguments than an existing
> one is like currying. Except that the idea behind "currying" is that
> this is /automatic/. You don't have to code it yourself. It's
> automatically available for all functions.

Maybe that's what scrambles my mind whenever I read "Haskellists'" 
explanations of stuff: They're so proud that Haskell does it 
automatically for you, that they tend to deny the obvious parallels.

So yes: Currying *is* like writing a function that takes fewer 
arguments, calling the original one and supplying (unchangeable) 
defaults for the missing arguments.

And yes, apparently Haskell provides syntactic sugar for that. Wow. Big 
deal.

> Finally, like I said, currying works backwards too: If a function call
> happens to return a function as its result, you can just keep appending
> arguments. "head function_list 7" and all that.

Again, nice-to-have syntactic sugar, but nothing conceptually 
fascinating (as you noted yourself).

> That said, you could probably design some sort of object that has
> methods for adding arguments, N at a time, and when it gets enough
> arguments, it yields an answer. And that might reasonably be described
> as currying.

No. That might reasonably be described as nothing but bullshit.


Post a reply to this message

From: clipka
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 12:41:51
Message: <4f9434cf$1@news.povray.org>
Am 22.04.2012 17:56, schrieb Orchid Win7 v1:
> On 22/04/2012 01:43 PM, Warp wrote:
>> Orchid Win7 v1<voi### [at] devnull> wrote:
>>> 1. You can take a 5-argument function, pass it 2 argument, and get a
>>> 3-argument function as the result.
>>
>> Would this be currying in C++?
>>
>> std::function<int(int)> multiplierFunction(int multiplier)
>> {
>> return [multiplier](int value) { return value * multiplier; };
>> }
>>
>> The above function returns a function that takes an integral as parameter
>> and returns it multiplied by the specified multiplier.
>
> Yeah, I think that would satisfy my idea of "curried function".
>
> The question is, does
>
> multiplierFunction(3)(4)
>
> or similar yield a 12?

Sure, why not? multiplierFunction(3) returns a valid function, so 
invoking its () operator calls the function with the respective 
parameter(s).

(You could achieve the same syntax by having multiplierFunction() return 
an object with an overridden () operator rather than a function, but of 
course that would be cheating.)


Post a reply to this message

From: Warp
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 12:51:29
Message: <4f943711@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> So yes: Currying *is* like writing a function that takes fewer 
> arguments, calling the original one and supplying (unchangeable) 
> defaults for the missing arguments.

  I think that the difference is that the new function is not static,
but it's generated dynamically. (In other words, what you end up is a
new function which fixes some of the parameters of the original function,
but the values to which they are fixed is determined at runtime rather
than at compile time.)

  This means, if I understand correctly, that you could for example create
such functions in a loop (or, as we are talking about functional languages,
in a recursive manner), which is quite difficult to achieve with static,
compile-time functions. (I suppose you could try to emulate this in a
statically typed language with no lambda functions, but you would need
some kind of stack or something where the fixed parameter values are
stored.)

  There are probably even deeper implications.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 12:53:52
Message: <4f94379f@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> The question is, does

>    multiplierFunction(3)(4)

> or similar yield a 12?

  Yes.

-- 
                                                          - Warp


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

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