Created
January 25, 2011 23:14
-
-
Save mikehadlow/795905 to your computer and use it in GitHub Desktop.
The simplest possible Monad in three languages: C#, F# and Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace Suteki.Monads | |
{ | |
public class FunctionComposition | |
{ | |
public void AddTwoNumbers() | |
{ | |
var result = | |
from a in 3.ToIdentity() | |
from b in 4.ToIdentity() | |
select a + b; | |
Console.Out.WriteLine("result.Value = {0}", result.Value); | |
} | |
} | |
// The simplest possible Monad, Identity | |
// it does nothing more than contain a value of the given the type | |
public class Identity<T> | |
{ | |
public T Value { get; private set; } | |
public Identity(T value) | |
{ | |
Value = value; | |
} | |
} | |
public static class IdentityExtensions | |
{ | |
// These two functions make Identity<T> a Monad. | |
// a function 'Unit' or 'Return' or 'ToIdentity' that creates a new instance of Identity | |
public static Identity<T> ToIdentity<T>(this T value) | |
{ | |
return new Identity<T>(value); | |
} | |
// a function 'Bind', that allows us to compose Identity returning functions | |
public static Identity<B> Bind<A, B>(this Identity<A> a, Func<A, Identity<B>> func) | |
{ | |
return func(a.Value); | |
} | |
// SelectMany is required for Linq syntax | |
public static Identity<C> SelectMany<A, B, C>(this Identity<A> a, Func<A, Identity<B>> func, Func<A, B, C> select) | |
{ | |
return select(a.Value, func(a.Value).Value).ToIdentity(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Identity<'a> = Identity of 'a | |
let getValue (a : Identity<'a>) = match a with Identity x -> x | |
let mreturn x = Identity x | |
let bind (a : Identity<'a>) (f : 'a -> Identity<'b>) = f (getValue a) | |
type IdentityBuilder() = | |
member x.Bind(a, f) = bind a f | |
member x.Return(a) = mreturn a | |
let identity = new IdentityBuilder() | |
let result = identity { | |
let! a = Identity 4 | |
let! b = Identity 3 | |
return a + b | |
} | |
printfn "result = %A" (getValue result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main ( | |
main | |
) where | |
data Identity a = Identity a | |
getValue (Identity a) = a | |
instance Monad Identity where | |
return a = Identity a | |
(>>=) a f = f $ getValue a | |
main = putStrLn $ show $ getValue $ do | |
a <- Identity 4 | |
b <- Identity 3 | |
return (a + b) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment