POV-Ray : Newsgroups : povray.off-topic : I'm in the mood for monads Server Time
29 Jul 2024 22:21:29 EDT (-0400)
  I'm in the mood for monads (Message 14 to 23 of 93)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Warp
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 06:40:01
Message: <4f93e001@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> > For instance,
> > I still don't understand what currying *really* is about, and every time
> > I try to suggest "is like this?" the answer is "not really".

> 1. You can take a 5-argument function, pass it 2 argument, and get a 
> 3-argument function as the result.

  But that's the thing: It sounds so trivial as to defy sense. Why give
a particular name to such a trivial thing? It's like calling the act of
taking a 3-dimensional vector and expanding it to a 4-dimensional one
"potatoing", or taking two integers and adding them together "bananaing",
or taking a class and adding another class as its member "orangeing".
Why give an obscure name to such a trivial operation?

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

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: Living in a box
Date: 22 Apr 2012 06:53:56
Message: <4f93e344@news.povray.org>
Le_Forgeron <jgr### [at] freefr> wrote:
> The overloading (?) of << and >> is already enough trauma when dealing
> with streams... or not.

> c = ceo << eke ;
> d = kaz << ekk ;

> one is a shift operation, the other is write in a stream... can you say
> which one ?

  People keep repeating that, and there's never any substance to the claim.

  I have been programming in C++ both as a hobby and professionally for
over 15 years now, and I have yet to encounter a piece of code where it's
confusing which operation is being performed.

> (and either c is an integer or a stream...)

  That's an especially dishonest example because it won't actually compile
if c is a stream because streams are not assignable.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: Living in a box
Date: 22 Apr 2012 06:59:45
Message: <4f93e4a1@news.povray.org>
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.)

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: Living in a box
Date: 22 Apr 2012 07:18:04
Message: <4f93e8ec@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> Listing #1:
>    Type1 x = foo();
>    Type2 y = bar(x);
>    Type3 z = baz(y);
>    return z;

  Btw, I don't know if this is exactly what you are looking for, but I think
it achieves at least close to what you are attempting:

    auto x = [](int i) { return i*2; };
    auto y = [x](int i) { return x(i*3); };
    auto z = [y](int i) { return y(i*5); };
    std::cout << z(3) << std::endl;

  (Capturing the other functions by value is far easier than taking them
as function parameters because this way you don't have to care about the
type of the anonymous function. Unfortunately lambda functions cannot yet
be templated, which is a bummer.)

  If you wanted to return that 'z' from a function, it's slightly less
intuitive (because function return values cannot be 'auto'). You have
to do it like this:

//--------------------------------------------------------------------
#include <iostream>
#include <functional>

std::function<int(int)> gimmeTheFunction()
{
    auto x = [](int i) { return i*2; };
    auto y = [x](int i) { return x(i*3); };
    auto z = [y](int i) { return y(i*5); };
    return z;
}

int main()
{
    auto func = gimmeTheFunction();
    std::cout << func(3) << std::endl;
}
//--------------------------------------------------------------------

-- 
                                                          - Warp


Post a reply to this message

From: James Holsenback
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 08:38:32
Message: <4f93fbc8@news.povray.org>
On 04/21/2012 06:14 PM, Stephen wrote:
> On 21/04/2012 10:17 PM, Orchid Win7 v1 wrote:
>> On 21/04/2012 09:56 PM, Stephen wrote:
>>> On 21/04/2012 9:01 PM, Orchid Win7 v1 wrote:
>>>> And that's basically /it/.
>>>
>>> Well it tells me nothing.
>>
>> 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.
>

Oh that's easy ... it's just the singular form of gonad ... THUD ... 
couldn't resist ;-)


Post a reply to this message

From: Warp
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 08:43:07
Message: <4f93fcda@news.povray.org>
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. To better understand
it, it's used eg. like this:

    auto doubler = multiplierFunction(2);
    auto tripler = multiplierFunction(3);
    auto nMultiplier = multiplierFunction(n);

    std::cout << doubler(5); // Will print "10"
    std::cout << tripler(5); // Will print "15"
    std::cout << nMultiplier(5); // Will print the result of 5*n

-- 
                                                          - Warp


Post a reply to this message

From: Stephen
Subject: Re: I'm in the mood for monads
Date: 22 Apr 2012 09:06:40
Message: <4f940260@news.povray.org>
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

-- 
Regards
     Stephen


Post a reply to this message

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

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

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