Coder Perfect

What’s the difference between a monad and a function in C#?


These days, there’s a lot of talk about monads. I’ve read a few articles and blog posts, but their examples don’t go far enough for me to properly grasp the concept. The reason for this is that monads are a functional language notion, hence the examples are in languages I haven’t dealt with before (because I haven’t done much with functional languages). I don’t understand the syntax well enough to completely follow the articles… but I can see there’s something worth learning.

I do, however, have a good understanding of C#, including lambda expressions and other useful features. I understand that C# only has a subset of functional properties, hence monads may not be possible to represent in C#.

However, surely it is possible to convey the concept? At least I hope so. Maybe you can present a C# example as a foundation, and then describe what a C# developer would wish he could do from there but can’t because the language lacks functional programming features. This would be fantastic, because it would convey the intent and benefits of monads. So here’s my question: What is the best explanation you can give of monads to a C# 3 developer?


(EDIT: By the way, I know there are at least 3 “what is a monad” questions already on SO. However, I face the same problem with them … so this question is needed imo, because of the C#-developer focus. Thanks.)

Asked by Charlie Flowers

Solution #1

The majority of what you do all day in programming is combine some functions to create larger functions. In most cases, your toolbox includes not only functions but also things like operators, variable assignments, and the like, but in most cases, your program combines many “computations” into larger computations that will be combined further.

This “combination of computations” is done using a monad.

The most fundamental “operator” for combining two computations is usually ;:

a; b

You mean “first do a, then do b” when you say this. The result a; b is essentially a computation that can be combined with extra information. A simple monad is a technique of combining little computations into larger ones. “Do the item on the left, then do the thing on the right,” says the ;.

In object-oriented languages, another item that might be considered a monad is the. You’ll frequently come across something like this:


“Evaluate the computation on the left, and then call the method on the right on the result of that,” the. essentially means. It’s a little more sophisticated version of ; for combining functions/computations. And, because it’s a technique of joining two computations into a new calculation, the concept of chaining things together with. is a monad.

This pattern is another fairly common monad with no special syntax:

rv = socket.bind(address, port);
if (rv == -1)
  return -1;

rv = socket.connect(...);
if (rv == -1)
  return -1;

rv = socket.send(...);
if (rv == -1)
  return -1;

A return result of -1 indicates failure, but even if you have a lot of API calls to combine in this way, there’s no way to abstract out this error checking. This is essentially another monad that combines function calls according to the condition “if the function on the left returned -1, do the same, else call the function on the right.” We could simply write: If we had an operator >>= that did this, we could simply write:

socket.bind(...) >>= socket.connect(...) >>= socket.send(...)

It would make things more readable and help to abstract out our unique manner of mixing functions, allowing us to avoid repeating ourselves.

There are many more methods to combine functions/computations that are helpful as a general pattern that can be abstracted in a monad, allowing the monad’s user to write much more concise and straightforward code because the monad handles all of the bookkeeping and management for the utilized functions.

For example, the above >>= may be expanded to “perform the error checking and then call the right side on the socket that we obtained as input,” eliminating the need to provide socket several times:

new socket() >>= bind(...) >>= connect(...) >>= send(...);

The formal definition is a little more involved since you have to think about how to receive the result of one function as an input to the next one, if that function requires it, and you have to make sure that the functions you combine fit together in the way you want to combine them in your monad. However, the core idea is that you codify numerous ways of combining functions.

Answered by sth

Solution #2

I’ve been asking this question for a year now. After uploading it, I spent a few months learning Haskell. I really liked it, however I put it down just as I was getting ready to start Monads. I returned to work and concentrated on the technologies that my project necessitated.

I came back and re-read these responses last night. Most importantly, I re-read the precise C# example mentioned above in the text comments of the Brian Beckman video. I’ve decided to post it immediately here because it was so clear and informative.

Not only do I feel like I understand exactly what Monads are as a result of this comment… I’m starting to realize that I’ve written several Monads in C#… or, at the very least, quite close, and attempting to solve the same issues.

So, here’s the comment – all of this is an exact quote from sylvan’s comment:

Answered by Charlie Flowers

Solution #3

Deferred processing is essentially what a monad is. If you’re trying to write code with side effects (like I/O) in a language that doesn’t allow them and only allows pure calculation, one way to get around it is to say, “OK, I know you won’t do side effects for me, but can you kindly compute what would happen if you did?”

It’s a bit of a ruse.

Now, that explanation will help you grasp monads’ overall purpose, but the devil is in the specifics. What method do you use to calculate the consequences? It isn’t always pretty.

For someone used to imperative programming, the best way to explain how it works is to say that it puts you in a DSL where operations that look syntactically similar to what you’re used to outside the monad are used to build a function that would do what you want if you could (for example) write to an output file are used instead. It’s almost (but not quite) like writing code in a string to be eval’d afterwards.

Answered by MarkusQ

Solution #4

I’m sure other users will go into greater detail, but I found this video to be helpful to a point, but I’m still not at the stage where I could (or should) start solving issues intuitively with Monads.

Answered by TheMissingLINQ

Solution #5

A monad can be thought of as a C# interface that classes must implement. This is a pragmatic answer that ignores all of the category theoretical math behind why you’d want to use these declarations in your interface and ignores all of the reasons why you’d want to use monads in a language that tries to avoid side effects, but as someone who understands (C#) interfaces, I found it to be a good place to start.

Answered by hao

Post is based on