Created
April 19, 2012 17:21
-
-
Save Thorium/2422428 to your computer and use it in GitHub Desktop.
Computational expressions / monad / builder example: Nullable
This file contains hidden or 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 BuilderExample | |
open System | |
//Example: nullable { ... } with combining functionality | |
type NullableBuilder() = | |
let hasValue (a:Nullable<'a>) = a.HasValue | |
member t.Return(x) = Nullable(x) | |
member t.Bind(x, rest) = | |
match hasValue x with | |
| false -> System.Nullable() //.NET null object | |
| true -> rest(x.Value) | |
let nullable = NullableBuilder() | |
let test = | |
nullable{ | |
let! a = System.Nullable(3) //"let!" calls builders Bind | |
let! b = System.Nullable(5) //"let!" calls builders Bind | |
//Inside computation expression(/monad): easy programming without Nullable-worries: | |
let mult = a * b | |
let sum = mult + 1 | |
return sum //"return" calls builders Return(x) | |
} | |
//val test : Nullable<int> = 16 | |
//------------------------------------------------------------------------------ | |
// using e.g. | |
// let! b = System.Nullable() | |
// would cause to return: | |
// val test : System.Nullable() | |
// own { ...} syntax is made with implementing Builder-class | |
// and (some of) the "interface" members | |
//------------------------------------------------ | |
// Further reading: | |
// "Interface" described in: http://msdn.microsoft.com/en-us/library/dd233182.aspx | |
// More info: http://blogs.msdn.com/b/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow-syntax.aspx | |
// Check also Reactive Extensions 2.0 with F# observe { ... }: | |
// https://github.com/panesofglass/FSharp.Reactive/blob/master/src/Observable.fs | |
// and: http://fssnip.net/tags/computation+builder and http://fssnip.net/tags/monad | |
This file contains hidden or 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
// The same in C-Sharp. | |
using System; | |
namespace NullableExtensionMonad | |
{ | |
/// <summary> | |
/// This is not so much useful class as it is LINQ-demo. | |
/// </summary> | |
static class NullableWrapperExtensions | |
{ | |
public static TOut? Select<TIn, TOut>(this TIn? source, Func<TIn, TOut> selector) | |
where TIn: struct where TOut : struct | |
{ | |
return source.HasValue ? selector(source.Value) : new TOut?(); | |
} | |
public static TOut? SelectMany<TIn, TIn2, TOut>(this TIn? source, Func<TIn, TIn2?> valueSelector, Func<TIn, TIn2, TOut> resultSelector) | |
where TIn : struct where TIn2 : struct where TOut : struct | |
{ | |
var newVal = source.HasValue ? valueSelector(source.Value) : new TIn2?(); | |
return source.HasValue && newVal.HasValue ? resultSelector(source.Value, newVal.Value) : new TOut?(); | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var res1 = from a in (int?)3 | |
from b in (int?)5 | |
select a * b + 5; | |
Console.WriteLine("First has value: {0}, the first is : {1}", res1.HasValue, res1); | |
var res2 = from a in (int?)null | |
from b in (int?)5 | |
select a + b + 5; | |
Console.WriteLine("Second has value: {0}, the second is : {1}", res2.HasValue, res2); | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment