POV-Ray : Newsgroups : povray.off-topic : I'm in the mood for monads Server Time
29 Jul 2024 20:27:05 EDT (-0400)
  I'm in the mood for monads (Message 24 to 33 of 93)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
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

From: Warp
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 13:03:36
Message: <4f9439e8@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> (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.)

  That's kind of what the C++ lambda does internally: It puts the captured
variables in some kind of internal struct, which the function then operates
with (similarly to how a class member function operates with the object
using the 'this' pointer). You could achieve a similar behavior by writing
a class, but a lambda achieves this with significantly less effort.

  There is a significant difference to a class, though. In this example
std::function<int(int)> can manage *any* lambda function that takes an
int and returns an int, not just ones that have captured a 'multiplier'
variable and perform a "value * multiplier" on it.

  If you implemented the functionality of the example I wrote with a
class, you would be fixing the "lambda" function to be only and exactly
a multiplier function that has to be used with exactly your class and
nothing else. std::function<int(int)> has no such limitation. Any function
(be it a static function or a lambda) that takes an int and returns one
will do.

  This can make a difference especially with non-templated functions that
take a std::function as parameter. (One advantage of std::function over a
generic functor is that the former does not require for the code that uses
it to be templated and thus doesn't suffer form the few limitations that
templated code has.)

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: Living in a box
Date: 22 Apr 2012 13:15:46
Message: <4f943cc2@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> >    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?

  A variable that points to such an anonymous function works like any
function pointer, which means you can call it like a regular function.
Thus if you have, for example:

    auto func = [](int x) { return 2*x; };

then you can simply call it like

    func(5);

  Templates taking a functor as parameter work the same way. You could
have something like:

    template<typename T, typename Comparator>
    bool compare(const T& value1, const T& value2,
                 const Comparator& comparatorFunction)
    {
        return comparatorFunction(value1, value2);
    }

  In the above example any comparator function will do (a comparator
function is something that behaves like a function taking two parameters
and returns a boolean). This can be a regular function, a functor (a class
that behaves like a function), a lambda, or an object of type std::function.
Thus you can call it eg. like:

    compare(1, 3, [](int v1, int v2) { return v1 < v2; })

-- 
                                                          - Warp


Post a reply to this message

From: James Holsenback
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 13:44:28
Message: <4f94437c$1@news.povray.org>
On 04/22/2012 09:06 AM, Stephen wrote:
> On 22/04/2012 1:38 PM, James Holsenback wrote:
>> On 04/21/2012 06:14 PM, Stephen wrote:
>
>>>
>>> I should have said that I am none the wiser. I still do not know what a
>>> monad is.
>>>
>>
>> Oh that's easy ... it's just the singular form of gonad ... THUD ...
>> couldn't resist ;-)
>
> That calls for a kick in both monads. :-P
>

hmmmm ... nonads (well that's self explanatory) better yet faux-nads ... 
someone who thinks that gotta pair. OK I'll stop now ;-)


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.