`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
{
{
/*请自行填补*/
}

{
/*请自行填补*/
}

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

{
/*请自行填补*/
}```
posted on 2013-07-26 19:12 陈梓瀚(vczh) 阅读(14594) 评论(15)  编辑 收藏 引用 所属分类: 启示

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 20:05 | 幻の上帝

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 20:06 | 幻の上帝
clang什么时候彻底支持MS ABI？cl什么时候C++11 feature complete（好吧也许该说是C++14）？顺便给我搞个支持arm-eabi-none的后端过来？

（卧槽为啥用FF回复就说是广告……）  回复  更多评论

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 20:07 | 幻の上帝
clang什么时候彻底支持MS ABI？cl什么时候C++11 feature complete（好吧也许该说是C++14）？顺便给我搞个支持arm-none-eabi的后端过来？
回复  更多评论

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 20:29 | unknown

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 20:33 | 陈梓瀚(vczh)
@幻の上帝

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换[未登录] 2013-07-26 21:01 | me

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-26 21:12 | DiryBoy

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-27 04:21 | ccsdu2009

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-27 06:20 | jagd
> 而且我们也都知道，gcc在windows上编译的慢出来的代码还不如VC++，gcc在linux上编译的慢还不如clang

回复  更多评论

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-27 06:34 | 陈梓瀚(vczh)
@jagd

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-27 13:56 | jagd
@陈梓瀚(vczh)

------ AMP 分割线 ---------

----- GCC vs VC++ 分割线 --------

----------

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-07-27 19:18 | 陈梓瀚(vczh)
@jagd

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2013-10-25 22:15 | lichray
gcc不知道是谁投资的

Funding comes from GNU of course, payed developers come from RedHat, Intel (yes, although they have their own compiler), and Google (they focus more on LLVM now).  回复  更多评论

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2015-01-14 23:40 | Sorra

public class _TakeWhile<T> 里面不太明白。

_state_enumerator这个field不存在？case 3有点多余，可以融到case 1里？

# re: 如何设计一门语言（八）&mdash;&mdash;异步编程和CPS变换 2015-01-22 23:49 | dramforever

2. Count牛逼的后两个没写等号

 只有注册用户登录后才能发表评论。 【推荐】100%开源！大型工业跨平台软件C++源码提供，建模，组态！ 相关文章: