How to design a programming language (eight) asynchronous programming and CPS transformation

Source: Internet
Author: User
Tags abstract error code expression integer regular expression

About this topic, actually in (vi) inside already discussed half. Learn Haskell know, this world many things can use Monad and comonad to put some complex code to abstract into a simple, read the form. Their differences, like using JS to do a complex with a few layers of animation, directly written and jquery "callback" written out of the same code. The former can not be used, the latter can not be seen. Is there anything that can be used and can be seen? I can only see it in Haskell, C #, and F # now. As for why, of course, because they all support monad and Comonad. But C # as a language that does not "use libraries to transform language" as an important feature is not intended to allow you to abstract things into monad, and then write them easily, like Haskell and F #. C # has only built-in yield return and async await such things.

The "Use of library to transform language" as an important feature of the language is not much, we are familiar with only Lisp and C + +, unfamiliar with F #. F # has a function of type provider in addition to computation expression. Is that you can write a small piece of code in your current program that tells the compiler to execute the following when compiling your code (a bit like a chicken egg problem but not really). This code can generate new code (instead of modifying existing code like Lisp), and then use it for the rest of your program. Example I will not lift, interested everyone to see here: http://msdn.microsoft.com/en-us/library/vstudio/hh361034.aspx. There is an example of how to create a strongly typed regular expression library inside F #, and unlike Boost's spirit or Xpress, regular expressions are still written using strings. This regular expression can be compiled to know that you have the wrong things, do not have to wait until the run to know.

Haskell and F # have experimented with Monad/comonad and computation expression respectively, The idea is to allow users to express their own things that can be handled naturally by continuation passing style transformations in a way that does not get out of control (Lisp's macro). Before introducing the power of C # 's async await, let's talk about the practices of Haskell and F #. Why do you follow this procedure because Haskell's monad is the least expressive, followed by F #, and then in C #. Of course, C # is not going to let you write a type that supports the CPS transformation. As a supplement, I will at the end of this article talk about the language I am designing recently, how to transform C # 's yield return and async await into libraries rather than compiler functions.

I'm going to throw away all the academic stuff and just leave things that are related to actual development.

I. Haskell and Monad

Haskell face the problem is actually relatively simple, the first is because the Haskell program can not have an implicit state, the second is because Haskell no statement only expression. This means that all of your control streams must be done with recursion or CPS. From this point of view, Monad is also considered as an application of CPS. So I explained to you how Monad is operating, decided to fry rehash, said the story of error code. This story has been said in (seven), but today with Haskell, do not have an exotic.

When you use C + +, we all feel that processing error code is a very annoying thing. I also do not know why those people put exception not, to the error code so like, until one day, I heard a fool on Weibo said: "Error code means I can ignore him." I finally understand, this person is a real idiot. But Haskell is still very sympathetic to these people, just like Jesus, who believes in him can be eternal life, the idiot can also. Unfortunately, the idiot is not monad, so Jesus is just a legend.

Since Haskell does not have "reference parameters", all results must appear in the return value. Therefore, if you want to do error code inside the Haskell, you have to return a data. Data is the same as the C-language union, the difference is that the data is strongly typed, and C's union accidentally will be silly:

Data unsure a = sure a | Error string

Then give some of the necessary implementations, first of all, functor:

Instance functor unsure where
Fmap f (sure x) = sure (f x)
Fmap F (Error e) = Error E

The rest is Monad:

Instance Monad unsure where
return = Sure
Fail = Error
(sure s) >>= f = f S
(Error E) >>= f = Error E

It doesn't look like much, it adds up to just eight lines and completes the statement of error code. Of course, this is not to see the powerful power of monad, so we also need a code. For example, to include a fraction of an array, and then convert all fractions into "cool", "General" and "silly", and reconstruct into an array. A real Haskell programmer breaks down this program into two halves, and the first half is, of course, a thing that turns fractions into numbers:

Tag:: integer-> unsure string
Tag f = 
    if f < 0 then Error "score must be between 0-100" else
    if f<60 then sure "Silly" else
    if f<90 then sure "General" else
    if f<=100 then sure "the" "Else
    Error" score must be between 0-100 "

The back is a loop:

Tagall:: [integer]-> unsure [string]
    
tagall [] = []
tagall (x:xs) = do
    -i-<-Tag x
    remains <-tagall xs return
    first:remains

Tagall is a cycle, the input of the things each one with the tag over again. If one of the tag returns fails, the entire Tagall function fails and returns an error. If all succeeds, then the Tagall function returns the entire processed array.

Of course a loop is written as a non-tail recursion is not a real Haskell programmer will do things, real Haskell programmers will do things like this (after the >>= expansion you may feel that this function is not tail recursion, but because Haskell is call by Need, so it's actually going to be a tail-recursive function):

Tagall:: [integer]-> unsure [string]
tagall xs = reverse $ tagall_ xs [] where
    tagall [] ys = sure Ys
  tagall (x:xs) ys = do
        y <-Tag x
        tagall xs (y:ys)

Why is there no code in the code that "checks the return value of the tag function"? This is the power of Haskell's monad expressive power. The use of Monad starts with the Do keyword, and the expression can be defined as this:

Monadexp
    :: = "Do" Fragmentnotnull
    
fragmentnotnull
    :: = [pattern "<-"] Expression
    
EOL Fragmentnull
    :: = Fragmentnotnull
    :: =ε

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.