POV-Ray : Newsgroups : povray.off-topic : Monads in C# Server Time
29 Jul 2024 02:28:45 EDT (-0400)
  Monads in C# (Message 10 to 19 of 29)  
<<< Previous 9 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Orchid Win7 v1
Subject: Re: Monads in C#
Date: 14 Mar 2013 18:39:43
Message: <514251af$1@news.povray.org>
On 14/03/2013 08:24 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>> Again, the problem is that we need to write a method which examines TWO
>> objects which must be of THE SAME class.
>
> I don't understand at all what that even means.
>
> Start by explaining (briefly) what "examines" means in this context.

Consider another example: Let's say you want to do something like

   public abstract class Tree
   {
     ...
     public abstract Tree Union(Tree other);
     ...
   }

So we can now write SplayTree, HeapTree, SearchTree, etc as subclasses 
of Tree. But the thing is... you can only Union() two trees together if 
they are THE SAME TYPE of tree. So you can take the union of two 
SplayTrees, or the union of two HeapTrees, but NOT the union of a 
SplayTree and a HeapTree.

But the type signature above does not express this constraint. It says 
that you can union *any* two objects so long as they are both Trees - 
which is wrong.

That's the basic problem with writing a monad interface in C# (or Java, 
for that matter). You could do a run-time type check and throw an 
exception if the types don't match, of course. But I haven't yet figured 
out how to enforce the constraint at compile-time.

(Having asked some questions on stack overflow, it appears it might 
actually be possible in C# though... I'll give it a go tomorrow.)


Post a reply to this message

From: clipka
Subject: Re: Monads in C#
Date: 15 Mar 2013 02:08:12
Message: <5142bacc$1@news.povray.org>
Am 14.03.2013 22:20, schrieb Anthony D. Baye:

>
http://stackoverflow.com/questions/2704652/monad-in-plain-english-for-the-oop-programmer-with-no-fp-background/2704795#
> 2704795

I guess this one about wraps it up nicely (emphasis added):

--------------------------------
Monads are typically used to solve problems like:

     * I need to make new capabilities for this type and still combine 
old functions on this type to use the new capabilities.
     * I need to capture a bunch of operations on types and represent 
those operations as composable objects, building up larger and larger 
compositions until I have just the right series of operations 
represented, and then I need to start getting results out of the thing
     * I NEED TO REPRESENT SIDE-EFFECTING OPERATIONS CLEANLY IN A 
LANGUAGE THAT HATES SIDE EFFECTS

(Note that these are basically three ways of saying the same thing.)
--------------------------------

With the whole OO concept being /centered/ around operations with 
side-effects (namely modifying the object's internal state), this boils 
down to saying that monads are NOT NEEDED in an OO language. (Or, in 
other words, that monads do something that is already inherent in the OO 
concept anyway.)

I think it might also be fair to say that monads are a way to express 
certain OO ideas in functional languages.


Post a reply to this message

From: clipka
Subject: Re: Monads in C#
Date: 15 Mar 2013 02:25:48
Message: <5142beec$1@news.povray.org>
Am 14.03.2013 23:39, schrieb Orchid Win7 v1:
> On 14/03/2013 08:24 PM, Warp wrote:
>> Orchid Win7 v1<voi### [at] devnull>  wrote:
>>> Again, the problem is that we need to write a method which examines TWO
>>> objects which must be of THE SAME class.
>>
>> I don't understand at all what that even means.
>>
>> Start by explaining (briefly) what "examines" means in this context.
>
> Consider another example: Let's say you want to do something like
>
>    public abstract class Tree
>    {
>      ...
>      public abstract Tree Union(Tree other);
>      ...
>    }
>
> So we can now write SplayTree, HeapTree, SearchTree, etc as subclasses
> of Tree. But the thing is... you can only Union() two trees together if
> they are THE SAME TYPE of tree. So you can take the union of two
> SplayTrees, or the union of two HeapTrees, but NOT the union of a
> SplayTree and a HeapTree.

Well, this can easily be solved by making Union non-abstract and having 
it call more primitive abstract functions; e.g (using pseudocode as I 
currently don't have C# syntax memorized):

   public abstract class Tree
   {

     public abstract Tree copy();
     public abstract Iterator<Leaf> leaves();
     public abstract void addLeaf(Leaf l);

     public final Tree Union(Tree other)
     {
       Tree newTree = this.copy();
       foreach(Leaf i in other.leaves())
         newTree.addLeaf(i);
     }
   }

There. Problem solved.

Note that in OO languages it is customary to use non-lazy evaluation 
(because objects may change, so lazy evaluation is prone for effects 
that OO programmers don't expect), so there's nothing conceptually wrong 
with copying the leaves rather than creating some "meta-tree" that 
provides tree-like operations on a compound of two tree objects.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Monads in C#
Date: 15 Mar 2013 04:34:16
Message: <5142dd08$1@news.povray.org>
>> So we can now write SplayTree, HeapTree, SearchTree, etc as subclasses
>> of Tree. But the thing is... you can only Union() two trees together if
>> they are THE SAME TYPE of tree. So you can take the union of two
>> SplayTrees, or the union of two HeapTrees, but NOT the union of a
>> SplayTree and a HeapTree.
>
> Well, this can easily be solved by making Union non-abstract and having
> it call more primitive abstract functions; e.g (using pseudocode as I
> currently don't have C# syntax memorized):
>
> public abstract class Tree
> {
>
> public abstract Tree copy();
> public abstract Iterator<Leaf> leaves();
> public abstract void addLeaf(Leaf l);
>
> public final Tree Union(Tree other)
> {
> Tree newTree = this.copy();
> foreach(Leaf i in other.leaves())
> newTree.addLeaf(i);
> }
> }
>
> There. Problem solved.

Note that taking the union of (say) two heap trees is a O(log N) 
operation, whereas what you just wrote is O(N).

You can, of course, NOT write an abstract interface, and just write a 
concrete Union() method [with a different type signature] for each 
concrete Tree class. That works just fine. [But now you can't write code 
that works over any Tree type and expect to do unions.]

But anyway. The example illustrates the problem. Taking the Bind() of 
two different monads isn't even *defined*. There's no sensible answer. 
So until I can find a solution to that...


Post a reply to this message

From: Orchid Win7 v1
Subject: C# monads
Date: 28 Mar 2013 09:03:47
Message: <51543fb3$1@news.povray.org>
On 13/03/2013 09:30 PM, Orchid Win7 v1 wrote:
> OK, so just for giggles, I tried to implement monads in C#.
>
> The short version: It appears that I can create a class with forms a
> monad, however it appears to be impossible to define the concept of
> "being a monad" such that you can write code which polymorphically works
> for any monad.

It appears I missed the elephant in the room. Apparently C# already 
*has* several classes which form monads, and even a special monad 
comprehension syntax for dealing with them.

Consider the following Haskell parser:

   identifier :: Parser String
   identifier = do
     leading  <- many space
     first    <- letter
     rest     <- many alphanum
     trailing <- many space
     return ([first] ++ rest)

Now consider the following C# LINQ query:

   Parser<string> identifier =
     from leading in Parse.Whitespace.Many()
     from first in Parse.Letter.Once()
     from rest in Parse.LetterOrDigit.Many()
     from trailing in Parse.Whitespace.Many()
     select new string(first.Concat(rest).ToArray());

Notice any similarity?

C# *already* has monads. The designers of LINQ even explicitly mention 
Haskell and monads as influencing their design.

So much for "only functional programmers understand monads and only 
functional programmers need monads"... :-P Monads are in fact one of the 
star features of a highly commercially successful programming platform.

(Although I'll admit LINQ is definitely tailored more towards 
*container* monads rather than being a general monad framework.)

I notice in passing that there is no "interface" which describes all the 
methods you have to implement to make a monad. (Or to make something 
that LINQ will work on.) Rather, it uses a strange system of "extension 
methods" - a very un-OO concept, if you look it up. But anyway, LINQ 
queries let you easily write monadic expressions without drowning in a 
sea of lambda functions.


Post a reply to this message

From: Warp
Subject: Re: Monads in C#
Date: 28 Mar 2013 09:51:16
Message: <51544ad4@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> It almost looks like it's describing inheritance. What is

> "First, what is an "amplifier of types"? By that I mean some system
> which lets you take a type and turn it into a more special type. For
> example, in C# consider Nullable<T>. This is an amplifier of types. It
> lets you take a type, say int, and add a new capability to that type,
> namely, that now it can be null when it couldn't before."

> other than inheritance? The next paragraphs also seem to be talking
> about inheritance.

> Of course the text then proceeds into blabbering about something that's
> hard to understand and seems quite inconsequential. Something about
> binding (which sounds like dynamic binding in inheritance, but apparently
> isn't?)

Still waiting for an answer to this...

-- 
                                                          - Warp


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Monads in C#
Date: 1 Apr 2013 09:55:32
Message: <515991d4@news.povray.org>
>> It almost looks like it's describing inheritance. What is
>
>> "First, what is an "amplifier of types"? By that I mean some system
>> which lets you take a type and turn it into a more special type. For
>> example, in C# consider Nullable<T>. This is an amplifier of types. It
>> lets you take a type, say int, and add a new capability to that type,
>> namely, that now it can be null when it couldn't before."
>
>> other than inheritance? The next paragraphs also seem to be talking
>> about inheritance.
>
>> Of course the text then proceeds into blabbering about something that's
>> hard to understand and seems quite inconsequential. Something about
>> binding (which sounds like dynamic binding in inheritance, but apparently
>> isn't?)
>
> Still waiting for an answer to this...

OK, so now I'm back from London, let's take a stab at this...

The originally quoted answer doesn't make a huge amount of sense to me. 
I mean, I see where the guy is trying to go, but it's not a great metaphor.

Let's say you have a Customer type. Using this, you can construct a 
List<Customer> type, which extends Customer with the ability to have 
multiple values. Similarly, Parser<Customer> extends the Customer type 
with the ability to read a customer from a string.

Except that, really, that's a rather odd way of looking at things. I 
mean, a list of customers isn't really much like a customer at all - 
it's a list! And a parser of customers isn't a customer either; it's a 
thing that might produce a customer.

The "binding" refers to binding the result of a parser (or whatever) to 
a function. In other words, you run the parser, and pass its result 
through a function to generate the final result. Really, a monad is 
simply a specific way of chaining operations together; nothing more 
complicated than that.


Post a reply to this message

From: Warp
Subject: Re: Monads in C#
Date: 1 Apr 2013 11:12:29
Message: <5159a3dc@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> Really, a monad is 
> simply a specific way of chaining operations together; nothing more 
> complicated than that.

And this is somehow different from just a regular function somehow?

-- 
                                                          - Warp


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Monads in C#
Date: 1 Apr 2013 17:04:24
Message: <5159f658$1@news.povray.org>
On 01/04/2013 04:12 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>> Really, a monad is
>> simply a specific way of chaining operations together; nothing more
>> complicated than that.
>
> And this is somehow different from just a regular function somehow?

Well, yeah, that's the crux of the matter.

In a pure language like Haskell, a *function* takes several inputs and 
produces an output, and that's all it's allowed to do. If you want to do 
something more complicated, you represent it as a monad.

Now, if you're working in an OO language, then you automatically have 
access to facilities like I/O, global variables, exception handling and 
so on. So you don't need a monad to represent these things.

But now suppose that you want some facility that the OO framework 
doesn't natively support. Whether it's non-deterministic computation or 
backtracking or partial failure or atomic transactions or whatever... A 
monad is one possible way of dealing with these things.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: C# monads
Date: 6 Apr 2013 07:21:42
Message: <51600546$1@news.povray.org>
On 28/03/2013 01:04 PM, Orchid Win7 v1 wrote:
> But anyway, LINQ
> queries let you easily write monadic expressions without drowning in a
> sea of lambda functions.

You'll be unsurprised to learn that I am currently about 40% of the way 
through implementing Parsec in C#. It turns out to be reasonably easy, 
although there are a few gotchas. (E.g., there is no C# function which 
both inserts an element into a list *and* returns the list. Which is 
annoying, since it seems you can't call void-functions from LINQ...)


Post a reply to this message

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

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