Create our first Monad

Source: Internet
Author: User

The previous article described how to use the amplified type, such as ienumerable<t> if we could find a way to combine the amplified type function, it would be easier to write a powerful program. We've already said a lot of combinations of functions that sound dry and hard. The combination of functions is actually simple programming, when we write code like this:

var customer=Customerdata.getbyid (customerId); var order=customer. Createorder ();

I'm just using a combination of functions, in this case, combining the GetByID and Createorder functions, and all the programs are a combination of functions, displayed or implicit.

As programmers we know how to combine parameters and return values is a function of unamplified type, which is natural.

Here are two simple functions. They have the same function signature, and I'll use the function delegate and the lambda expression instead of writing the static method directly:

func<int,int>add2=x=>x+2; Func<int,int>mult2=x=>x*2;

Combining the two functions is simple:

func<int,int>add2mult2=x=>mult2 (ADD2 (x));

We use the new function:

var r2=add2mult2 (5); Console.Out.WriteLine ("r2={0}", r2);

Result output r2=14

We've been doing this, but if we're going to combine functions that return the amplified type. First we need a amplified type to combine, in this case we choose the simplest amplified type. It encapsulates only one value, which we define as identity:

 Public class Identity<t>{ public T Value {get;  Set;}  Public Identity (T value) {Value=value;}}

Now we create two functions that return the amplified type

func<int,identity<int>>add2=x=>new Identity (x+2); Func<int,identity<int>>mult2=x=>new Identity (x*2);

If we combine the new function in the same way as above, the compilation will fail:

func<int,identity<int>>add2mult2=x=>mult2 (ADD2 (x));

Because ADD2 returns the identity<int> type, and the MULTI2 parameter is int, the type does not match, so the compilation fails. We can of course use the Value property,

func<int,identity<int>>add2mult2=x=>mult2 (ADD2 (x). Value)

This is possible, but the problem is that we want to combine any function of identity<t> to write X. Value. Don't forget that identity<t> is the simplest amplified type we can think of, in fact it doesn't work at all. If we want to use a useful amplified type, such as ienumerable<t>,task<t> or IMIGHTTHROWANEXCEPTION<T> We went back to the old way to add a lot of boilerplate code. We need to get rid of x. Value, how to do it?

What we're going to get is a function that combines ADD2 and mult2, and we define this function as bind. Looking at the example of the compilation failure above, we know the signature of bind. It needs to receive the return value of ADD2, a identity<t> type of value and MULT2, a signature func<int, identity<int>> function. To make bind more useful, we define it as a generic function, and it is an extension method:

// a function ' Bind ', allows us to compose Identity returning functions  Public Static Identity<b> bind<a,b> ( this identity<a>, Func<a, identity<b>>Func) {func ( A.value);}

Of course the bind function body simply invokes the A.value and passes the result to Func. We encapsulate the x.value with bind. The benefit is that this mechanism of handling amplified type depends on the type encapsulated by amplified type. The signature of bind is unique.

Now we can combine ADD2 and MULT2.

func<int,identity<int>>add2mult2=x=>add2 (x). Bind (MULT2);

We can use the functions generated by our new combination:

var r1=add2mult2 (5); Console.Out.WriteLine ("R1. value={0}", R1. Value);

Output r1=14

Let's create another useful extension method, toidentity, in order to create a new identity:

 Public Static Identity<t>toidentity<t>(T value) {returnnew identity<t>(value);}

Now we can write complex expressions with various identity values:

 var  result= " hello world!   ". Toidentity (). Bind (a=> 7 . Toidentity (). Bind (B=> ( new  DateTime (2010 , 1 , 11 )). Toidentity (). Bind (C=> (a  + "   " +b.tostring () +"                                              " +c.toshortdatestring ()) . Toidentity ()))); Console.WriteLine (Result. Value);  

Output Hello world!, 7, 11/01/2010

Here we receive a string, "Hello world!", convert it to a identity<string> convert integer 7 to Identity<int> convert date to identity< Datetime> We use the BIND function to skillfully access the encapsulated values, connect them and return a identity<string>.

The code above is not the most graceful one you've ever seen, but it's critical to take a look at the different types of amplified type that we can manipulate without accessing the Value property. Remember the two facts: first, in the future we can remove the lambda expression, followed by identity<t> may be the simplest amplified type. We can implement the function of any complexity.

Identity<t> is a monad,monad requirement to have a type constructor (Identity<t> yourself) and even a method: our bind and toidentity, that's all. You will find that bind and toidentity have different names in different languages. Toidentity is called Return,bind in Haskell and is called SelectMany in C # and will be seen later. It doesn't matter what their name is, it's the right signature:

Bind:func<identity<a>,func<a,identity<b>>,identity<b>>

Toidentity:func<t,identity<t>>

Bind is where we write Monad features, and is the only place where it is very powerful abstraction and is also the most attractive place for monad.

Next we'll see how to rename bind to SelectMany and use it in combination with toidentity so that we can use identity<t> in LINQ Monad

Create our first Monad

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.