inspired by csharp-monads, Haskell & F#
compatible with Unity3D
simplicity
predictability
composability
safety
concurrency
string FirstOf(string[] xs)
{
return xs.Length > 0 ? xs[0] : null;
}
var name = FirstOf(names);
var letters = name.Length; // Causes NullReferenceException
|
"The Maybe type encapsulates an optional value. A value of type Maybe[T] either contains a value of type T (Just[T]), or it is empty (Nothing[T])."
string FirstOf(string[] xs)
{
return xs.Length > 0 ? xs[0] : null;
}
var name = FirstOf(names);
var letters = name.Length; // Causes NullReferenceException
// vs.
Maybe<string> FirstOf(string[] xs)
{
return xs.Length > 0 ? Maybe.Just(xs[0]) : Maybe.Nothing<string>();
}
var name = FirstOf(names);
var letters = name.FromJustOrDefault(0,s => s.Length);
|
Maybe<string> FirstOf(string[] xs)
{
return xs.Length > 0 ? Maybe.Just(xs[0]) : Maybe.Nothing<string>();
}
Maybe<string> StartsWithA(string s)
{
return s.StartsWith("A") ? Maybe.Just(s) : Maybe.Nothing<string>();
}
Maybe<string> AtLeast5Chars(string s)
{
return s.Length >= 5 ? Maybe.Just(s) : Maybe.Nothing<string>();
}
var letters = FirstOf(names)
.Bind(StartsWithA)
.Bind(AtLeast5Chars)
.FromJustOrDefault(0,s => s.Length);
|
bool ValidPassword(string x)
{
if(x.Length < 8)
throw new System.Exception("Password needs at least 8 chars");
if(x.Contains("-"))
throw new System.Exception("Password needs to contain a dash");
return true;
}
var valid = false;
try
{
valid = ValidPassword(pw);
}
catch (Exception e)
{
Console.WriteLine("Validation error:"+e);
}
if(valid) Console.WriteLine("Validation succeeded");
|
"The Either type represents values with two possibilities: a value of type Either[T1,T2] is either Left[T1] or Right[T2]."
"The Either type is sometimes used to represent a value which is either correct or an error; by convention, Left is used to hold an error value and Right holds a correct value"
Either<Exception,string> ValidPassword(string x)
{
if(x.Length < 8)
return Either.Left<Exception,string>(new Exception("Password needs at least 8 chars"));
if (x.Contains("-"))
return Either.Left<Exception, string>(new Exception("Password needs to contain a dash"));
return Either.Right<Exception,string>(x);
}
var valid = ValidPassword(pw);
valid.IsLeft()
? Console.WriteLine("Validation error:" + valid.FromLeft())
: Console.WriteLine("Validation succeeded");
|
Either<Exception, string> AtLeast8Chars(string x)
{
return x.Length < 8
? Either.Left<Exception, string>(new Exception("Password needs at least 8 chars"))
: Either.Right<Exception, string>(x);
}
Either<Exception, string> ContainsDash(string x)
{
return x.Contains("-")
? Either.Left<Exception, string>(new Exception("Password needs to contain a dash"))
: Either.Right<Exception, string>(x);
}
Either<Exception,string> ValidPassword(string x)
{
return AtLeast8Chars(x)
.Bind(ContainsDash);
}
var valid = ValidPassword(pw);
valid.IsLeft()
? Console.WriteLine("Validation error:" + valid.FromLeft())
: Console.WriteLine("Validation succeeded");
|
HttpWebRequest webRequest;
void StartWebRequest()
{
webRequest.BeginGetResponse(FinishWebRequest, null);
}
void FinishWebRequest(IAsyncResult result)
{
var response = webRequest.EndGetResponse(result);
Console.WriteLine(response.ContentLength);
}
StartWebRequest(); // How do I get the response out?!?
|
"A compositional asynchronous computation, which, when run, will eventually produce a value of type T, or else raises an exception." - F# docs
Async<string> LoadHugeJsonAsync(Uri uri)
{
return () => "....json..."; //This could be a synchronous webrequest
}
var req = LoadHugeJsonAsync(new Uri("huge-json.com"));
// Run it synchronously/blocking
var result = req.RunSynchronously();
Console.WriteLine(result);
// Run it async with callback
var callback = new AsyncReplyChannel<string>(s =>
{
Console.WriteLine(s);
return Unit.Default;
});
req.StartAndReply(ch => callback);
|
Async<string> LoadHugeJsonAsync(Uri uri)
{
return () => "....json..."; //This could be a synchronous webrequest
}
Async<Dictionary<string, string>> ParseHugeJsonAsync(string json)
{
return () => new Dictionary<string, string>(); // There should be some parsing here
}
var req = LoadHugeJsonAsync(new Uri("huge-json.com"))
.Bind(ParseHugeJsonAsync);
// Get the dictionary synchronously
var dict = req.RunSynchronously();
|
Async<string> LoadHugeJsonAsync(Uri uri)
{
return () => "....json..."; //This could be a synchronous webrequest
}
var reqs = new []
{
LoadHugeJson(new Uri("huge-json.com/1")),
LoadHugeJson(new Uri("huge-json.com/2")),
LoadHugeJson(new Uri("huge-json.com/3"))
};
var results = reqs.Parallel().RunSynchronously();
foreach (var result in results)
{
Console.WriteLine(result);
}
|
github.com/wooga/Wooga.Lambda-CSharp