1+ < Query Kind = "Program" / >
2+
3+ void Main ( )
4+ {
5+ // left identity: monad construction doesn't change function behaviour
6+ ( "Hello" . bind ( trim ) . Value == trim ( "Hello" ) . Value ) . Dump ( ) ;
7+
8+ // right identity: re-wrapping doesn't change the value
9+ var helloMon = "Hello" . ret ( ) ;
10+ ( helloMon . bind ( hello => new nil < string > ( hello ) ) . Value == helloMon . Value ) . Dump ( ) ;
11+
12+ // associativity
13+ ( "Hello" . bind ( trim ) . bind ( sub ( 0 , 5 ) ) . Value ==
14+ "Hello" . bind ( v => trim ( v ) . bind ( sub ( 0 , 5 ) ) ) . Value ) . Dump ( ) ;
15+ }
16+
17+ Func < string , nil < string > > trim = x => x . Trim ( ) . ret ( ) ;
18+ Func < int , int , Func < string , nil < string > > > sub =
19+ ( int s , int l ) => x => x . Substring ( s , l ) . ret ( ) ;
20+ Func < string , nil < int > > len = x => x . Length . ret ( ) ;
21+ Func < int , nil < int > > sqr = x => ( x * x ) . ret ( ) ;
22+
23+ public class nil < T >
24+ {
25+ public nil ( T value ) => Value = value ;
26+ protected nil ( ) { }
27+
28+ public T Value { get ; set ; }
29+ public virtual bool HasValue => true ;
30+ public static nil < T > Nothing = new nothing < T > ( ) ;
31+ }
32+
33+ public class nothing < T > : nil < T >
34+ {
35+ public override bool HasValue => false ;
36+ }
37+
38+ public static class ext
39+ {
40+ public static nil < T > ret < T > ( this T value ) => new nil < T > ( value ) ;
41+
42+ // a.then(f).then(g).then(j)
43+ public static nil < C > bind < B , C > ( this B b , Func < B , nil < C > > fn )
44+ => b . ret ( ) . bind ( fn ) ;
45+
46+ // f(a).then(g).then(j)
47+ public static nil < C > bind < B , C > ( this nil < B > b , Func < B , nil < C > > fn )
48+ => b . HasValue ? fn ( b . Value ) : nil < C > . Nothing ;
49+ }
0 commit comments