// for testing/demonstrating the Option monad using System; public class option_test { public static Option some(double x) { // syntactic specialization return Option.Make(x); } public static Option NaN = Option.Nothing; public static Option safediv(double a, double b) { if (b!=0) return some(a/b); else return NaN; }//safediv // find largest value in an array of doubles, array can be empty public static Option smallest(double[] A) { if (A.Length==0) return NaN; int ai = 0; for(int i=1;iA[ai]) ai=i; return some(A[ai]); }//smallest // adopt the Convert.ToDouble method to return None instead of // throwing an exception, given an array of strings and an index public static Option ToDouble(string[] args, int i) { if (args==null || i<0 || i>=args.Length) return Option.Nothing; Option answer; try { answer = Option.Make(Convert.ToDouble(args[i])); } catch (Exception e) { Console.Error.WriteLine("ERROR: "+e.Message+" Returing None Option"); answer = Option.Nothing; } return answer; }//ToDouble, moving from exceptions to monads public static void Main(string[] args) { // get value from command-line args, or set to 2.0 as default: double divisor = ToDouble(args,0).unwrap_or(2.0); var Result = safediv(4,divisor); Console.WriteLine("division result: "+Result); Result .map( v => v + 1 ) //non-destructive construction of new Option .map_mut( v => v * -1) //possible destructive change to existing Option .and_then(v => { // can also call .map(..).flatten() Console.WriteLine("val is now "+v); return safediv(100,(v+3)) .pair(safediv(200,(v-3)), (x,y)=>x+y); // return sum of two safedivs }) .match( some: v => {Console.WriteLine("final result "+v);}, none: () => {Console.WriteLine("no result");} ); }//main for testing }//public class