# 如何设计一门语言（八）——异步编程和CPS变换 - λ-calculus（惊愕到手了欧耶，GetBlogPostIds.aspx） - C++博客

`data Unsure a = Sure a | Error string`

```instance Functor Unsure where
fmap f (Sure x) = Sure (f x)
fmap f (Error e) = Error e```

```instance Monad Unsure where
return = Sure
fail = Error
(Sure s) >>= f = f s
(Error e) >>= f = Error e```

```// Tag :: integer -> Unsure string
Tag f =
if f < 0 then Error "分数必须在0-100之间" else
if f<60 then Sure "傻逼" else
if f<90 then Sure "一般" else
if f<=100 then Sure "牛逼" else
Error "分数必须在0-100之间"```

```// TagAll :: [integer] -> Unsure [string]

TagAll [] = []
TagAll (x:xs) = do
first <- Tag x
remains <- TagAll xs
return first:remains```

TagAll是一个循环，把输入的东西每一个都用Tag过一遍。如果有一次Tag返回失败了，整个TagAll函数都会失败，然后返回错误。如果全部成功了，那么TagAll函数会返回整个处理后的数组。

```// 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)```

```MonadExp
::= "do" FragmentNotNull

FragmentNotNull
::= [Pattern "<-"] Expression EOL FragmentNull

FragmentNull
::= FragmentNotNull
::= ε```

1、第一样要是一个a<-e这样的东西。如果你不想给返回值命名，就省略“a<-”这部分
2、然后重复

1、先做e，然后把结果保存进a
2、然后做下面的事情

```// Count牛逼 :: integer -> integer -> integer –> Unsure integer

Count牛逼 chinese math english = do
a <- Tag chinese
b <- Tag math
c <- Tag english
return length [x | x <- [a, b, c], x == "牛逼"]```

```// Count牛逼 :: integer -> integer -> integer –> Unsure integer

Count牛逼 chinese math english
Tag chinese >>= \a->
Tag math >>= \b->
Tag english >>= \c->
return length [x | x <- [a, b, c], x == "牛逼"]```

>>=函数的定义是

```instance Monad Unsure where
return = Sure
fail = Error
(Sure s) >>= f = f s
(Error e) >>= f = Error e```

```// Count牛逼 :: integer -> integer -> integer –> Unsure integer

Count牛逼 chinese math english
case Tag chinese of {
Sure a -> case Tag math of {
Sure b -> case Tag english of {
Sure c -> Sure \$ length [x | x <- [a, b, c], x == "牛逼"]
Error e -> Error e
}
Error e -> Error e
}
Error e -> Error e
}```

```// Count牛逼 :: integer -> integer -> integer –> Unsure integer

Count牛逼 chinese math english
Tag chinese >>= \a->
Tag math >>= \b->
Tag english >>= \c->
return length [x | x <- [a, b, c], x == "牛逼"]```

F#虽然被设计成了一门函数式语言，但是其骨子里还是跟C#一样带状态的，而且编译成MSIL代码之后，可以直接让F#和C#互相调用。一个真正的Windows程序员，从来不会拘泥于让一个工程只用一个语言来写，而是不同的大模块，用其适合的最好的语言。微软把所有的东西都设计成可以强类型地互操作的，所以在Windows上面从来不存在什么“如果我用A语言写了，B就用不了”的这些事情。这是跟Linux的一个巨大的区别。Linux是没有强类型的互操作的（字符串信仰者们再见），而Windows有。什么，Windows不能用来做Server？那Windows Azure怎么做的，bing怎么做的。什么，只有微软才知道怎么正确使用Windows Server？你们喜欢玩的EVE游戏的服务器是怎么做的呢？

```let TagAll xs = unsure
{
let r = Array.create xs.length ""
for i in 0 .. xs.length-1 do
let! tag = Tag xs.[i]
r.[i]<-tag
return r
}```

```type UnsureBuilder() =
member this.Bind(m, f) = match m with
| Sure a -> f a
| Error s -> Error s
member this.For(xs, body) =unsure
{
match xs with
| [] -> Sure ()
| x::xs ->
let! r = Tag x
body r
return this.For xs body
}
.... // 还有很多别的东西```
`let unsure = new UnsureBuilder()`

```IEnumerable<T> Concat(this IEnumerable<T> a, IEnumerable<T> b)
{
foreach(var x in a)
yield return x;
foreach(var x in b)
yield return x;
}```

```async Task<T[]> SequencialExecute(this Task<T>[] tasks)
{
return ts;
}```

2. F#有computation expression，所以我们可以给自己定义的类型实现一个computation expression，从而让我们的类型可以用let!来操作。
3. C#有【什么】，所以我们可以给自己定义的类型实现一个【什么】，从而让我们的类型可以用【什么】来操作？

1. fmap对应于Select
2. >>=对应于SelectMany

```// Count牛逼 :: integer -> integer -> integer –> Unsure integer

Count牛逼 chinese math english = do
a <- Tag chinese
b <- Tag math
c <- Tag english
return length [x | x <- [a, b, c], x == "牛逼"]```

```Unsure<int> Count牛逼(int chinese, int math, int english)
{
return
from a in Tag(chinese)
from b in Tag(math)
from c in Tag(english)
return new int[]{a, b, c}.Where(x=>x=="牛逼").Count();
}```

C#有【什么】，所以我们可以给自己定义的类型实现一个【什么】，从而让我们的类型可以用【什么】来操作？

1. 首先把yield return修改成yield
2. 其次吧yield break修改成return
3. 然后再给函数打上一个叫做seq的东西，跟async对称，就当他是个关键字
4. 给所有CPS operator加上一个感叹号，让他变得更清楚（这里有yield、await和return）。为什么return也要加上感叹号呢？因为如果我们吧seq和aysnc摘掉的话，我们会发现return的类型是不匹配的。所以这不是一个真的return。

```seq IEnumerable<T> TakeWhile(this IEnumerable<T> source, Predicate<T> predicate)
{
foreach(var x in source)
{
if(!predicate(x))
return!;
yield! x
}
}

{
List<T> result=new List<T>();
foreach(var t in source)
{
var x = await! t;
if(!predicate(x))
return! result.ToArray();
}
return! result.ToArray();
}```

1. seq和async到底是什么？
2. seq下面的yield和return的类型分别是什么？
3. async下面的await和return的类型分别是什么？

1. 对于yield，yield接受了一个T，没有返回值。一个没有返回值的函数的continuation是什么呢？当然就是一个没有参数的函数了。
2. return则连输入都没有。
3. 而且yield和return都需要看到IEnumerator<T>。所以他们肯定有一个参数包含这个东西。

```public static class seq
{
public static IEnumerator<T> CreateCps<T>(Action<seq_Enumerator<T>>);
public static void yield<T>(seq_Enumerator<T> state, T value, Action continuation);
public static void exit<T>(seq_Enumerator<T> state /*没有输入*/ /*exit代表return，函数结束的意思就是不会有一个continuation*/);
}```

```public class seq_Enumerable<T> : IEnumerable<T>
{
public Action<seq_Enumerator<T>> startContinuation;

public IEnumerator<T> CreateEnumerator()
{
return new seq_Enumerator<T>
{
startContinuation=this.startContinuation)
};
}
}

public class seq_Enumerator<T> : IEnumerator<T>
{
public T current;
bool available;
Action<seq_Enumerator<T>> startContinuation;
Action continuation;

public T Current
{
get
{
return this.current;
}
}

public bool MoveNext()
{
this.available=false;
if(this.continuation==null)
{
this.startContinuation(this);
}
else
{
this.continuation();
}
return this.available;
}
}

public static class seq
{
public static IEnumerable<T> CreateCps<T>(Action<seq_Enumerator<T>> startContinuation)
{
return new seq_Enumerable
{
startContinuation=startContinuation
};
}

public static void yield<T>(seq_Enumeartor<T> state, T value, Action continuation)
{
state.current=value;
state.available=true;
state.continuation=continuation;
}

public static void exit<T>(seq_Enumeartor<T> state)
{
}
}```

```public class _TakeWhile<T>
{
seq_Enumerator<T> _controller;
Action _output_continuation_0= this.RunStateMachine;
int _state;
IEnumerable<T> _source;

IEnumerator<T> _source_enumerator;
Predicate<T> _predicate;
T x;

public void RunStateMachine()
{
while(true)
{
switch(this.state)
{
case 0:
{
this._source_enumerator = this._source.CreateEnumerator();
this._state=1;
}
break;
case 1:
{
if(this._state_enumerator.MoveNext())
{
this.x=this._state_enumerator.Current;
if(this._predicate(this.x))
{
this._state=2;
var input=this.x;
seq.yield(this._controller. input, this._output_continuation_0);
return;
}
else
{
seq.exit(this._controller);
}
}
else
{
state._state=3;
}
}
break;
case 2:
{
this.state=1;
}
break;
case 3:
{
seq.exit(this._controller);
}
break;
}
}
}
}```

```IEnumerable<T> TakeWhile(this IEnumerable<T> source, Predicate<T> predicate)
{
return seq.CreateCps(controller=>
{
var sm = new _Where<T>
{
_controller=controller,
_source=source,
_predicate=predicate,
};

sm.RunStateMachine();
});
}```

```public static class seq
{
public static IEnumerator<T> CreateCps<T>(Action<seq_Enumerator<T>>);
public static void yield<T>(seq_Enumerator<T> state, T value, Action continuation);
public static void exit<T>(seq_Enumerator<T> state /*没有输入*/ /*exit代表return，函数结束的意思就是不会有一个continuation*/);
}```

```public static class async
{
{
/*请自行填补*/
}

{
/*请自行填补*/
}

{
/*请自行填补*/
}
}

{
/*请自行填补*/

::...

ScrapBook :: Firefox Extension

或是邮件反馈可也:

粤ICP备18025058号-1

44049002000656

...::
```