WARNING: This is a long post. If you are not interested in Programming language theory then this will likely bore you.
----
So Monads are a big topic. Cause the word is fairly fancy. They were discovered within the tomes of Abstract Algebra by mages from the Haskell Tower hundreds of years ago in the early 80's. Since then haskell mages have written thousands of treatises on their use.
Recently with the sudden popularity of functional programming the common Sorcerer has found the use of monads. So there is suddenly a resurgence of interest in monads.
Monads are basically a higher level of design pattern. The encompass many things including - error handling, containers, Rules System ala prolog, probabilities, quantum mechanics, groups, continuations, parsers, AI etc...
Monad combinators allow a powerful composition type methodology, myself I noticed they might be useful for expressing AI and lots o game play type code. Basically the idea is you create a basic building block of components or behaviours and then combine them by interpreting them in a sub language that almost falls out for free. I am using them to make a powerful magic system where users can create spells.
For those of you on .NET if you use linq then you have used a monad before.
Specific Monads can be implemented in any language with generics. Ability to abstract over monads requires either having a stronger type system or a weaker e.g. dynamic/freely typed system. The use of monads is their ability to capture abstraction and turn them into pure power.
Traditional Maybe Monad Using Nemerle
variant Maybev[a] : Maybe[a]{
| Nothing
| Just { jst : a}
}
class Maybe [a] : MyMonad[a] {
public bind (m : Maybev[a] , mb : a -> Maybev) : Maybev {
match(m){
| Nothing => Maybev.Nothing();
| Just(x) => mb(x)
}}
public static @>>>= (m : Maybev[a] , mb : a -> Maybev) : Maybev{
m.bind(m,mb);
}
public mreturn (x : a) : Maybev[a]{
Maybev.Just(x);
}}
type Just[a] = Maybev[a].Just;
type Nothing[a] = Maybev[a].Nothing;
To use:
def o = Maybev.Just(3) >>>= fun(x1){
Maybev.Just(2) >>>= fun(x2){
Maybe().mreturn(x1 + x2)
}
}
o is Just(5). But that is nothing special.
F# has these things called Workflows and computation expressions. It lets you build and comprehend monads. It is the first language on .NET to have sugared support for monads. Using Nemerle's metaprogramming feature I was able to get similar to that.
In F# you can write:
attempt {
let! n1 = failIfBig inp1
let! n2 = failIfBig inp2
let sum = n1 + n2
return sum };;
In Nemerle with My monad dsl:
def opr = monadq(Maybe)[
p44 <== Just(3),
q44 <== Nothing(), //<--The computation will bail out here and return Nothing.
returns (p44 + q44)] //<== only gets here if ;
It is a macro which converts to the more verbose syntax. It works on any Monad. As well I am writing standard monad operations like map and fold etc as macros since the .NET type system is not flexible enough to allow that.
OUTPUT:
KKK
KKP
Car v bike
bike v Car
c v b
13
13 1
ConsoleApplication11del.Maybev`1+Nothing[System.Int32] No good Got 5 Got 5
vh?
Hi! 11 4 11 [2, 4, 6] [7, 10] (7, 10) 6 29 29 4
I was testing other things like currying, extensible matching, function operators and Existential types there.