1. C++
2. C#
3. F#
5. Ruby
6. Prolog

1. 面向对象→class
2. polymorphic type→template
3. intersection type→union / 函数重载
4. dependent type→带数字的模板类型
5. System F→在泛型的lambda表达式里面使用decltype（看下面的例子）
6. sub typing的规则→泛型lambda表达式到函数指针的隐式类型转换

```auto lambda = [](const auto& xs)
{
decltype(*xs.begin()) sum = 0;
for(auto x : xs)
{
sum += x;
}
return sum;
};```

```vector<int> a = { ... };
list<float> b = { ... };
deque<double> c = { ... };

int sumA = lambda(a);
float sumB = lambda(b);
double sumC = lambda(c);```

```doube(*summer)(const vector<double>&);
summer = lambda;```

```template<int m, int s, int kg>
struct unit
{
double value;

unit():value(0){}
unit(double _value):value(_value){}
};```

```template<int m, int s, int kg>
unit<m, s, kg> operator+(unit<m, s, kg> a, unit<m, s, kg> b)
{
return a.value + b.value;
}

template<int m, int s, int kg>
unit<m, s, kg> operator-(unit<m, s, kg> a, unit<m, s, kg> b)
{
return a.value - b.value;
}

template<int m, int s, int kg>
unit<m, s, kg> operator+(unit<m, s, kg> a)
{
return a.value;
}

template<int m, int s, int kg>
unit<m, s, kg> operator-(unit<m, s, kg> a)
{
return -a.value;
}

template<int m1, int s1, int kg1, int m2, int s2, int kg2>
unit<m1+m2, s1+s2, kg1+kg2>operator*(unit<m1, s1, kg1> a, unit<m2, s2, kg2> b)
{
return a.value * b.value;
}

template<int m1, int s1, int kg1, int m2, int s2, int kg2>
unit<m1-m2, s1-s2, kg1-kg2>operator/(unit<m1, s1, kg1> a, unit<m2, s2, kg2> b)
{
return a.value / b.value;
}```

```template<int m, int s, int kg>
unit<m, s, kg> operator*(double v, unit<m, s, kg> a)
{
return v * a.value;
}

template<int m, int s, int kg>
unit<m, s, kg> operator*(unit<m, s, kg> a, double v)
{
return a.value * v;
}

template<int m, int s, int kg>
unit<m, s, kg> operator/(double v, unit<m, s, kg> a)
{
return v / a.value;
}

template<int m, int s, int kg>
unit<m, s, kg> operator/(unit<m, s, kg> a, double v)
{
return a.value / v;
}```

```constexpr unit<1, 0, 0> operator""_meter(double value)
{
return value;
}

constexpr unit<0, 1, 0> operator""_second(double value)
{
return value;
}

constexpr unit<0, 0, 1> operator""_kilogram(double value)
{
return value;
}

constexpr unit<1, -2,1> operator""_N(double value) // 牛不知道怎么写-_-
{
return value;
}

constexpr unit<2, -2,1> operator""_J(double value) // 焦耳也不知道怎么写-_-
{
return value;
}```

```auto m = 16_kilogram; // unit<0, 0, 1>(16)
auto s = 3_meter; // unit<1, 0, 0>(3)
auto t = 2_second; // unit<0, 1, 0>(2)
auto a = s / (t*t); // unit<1, -2, 0>(3/4)
auto F = m * a; // unit<1, -2, 1>(12)```

```auto W = F * s; // unit<2, -2, 1>(36)
auto x = F + W; // bang!```

```double m = 16;
double s = 3;
double t = 2;
double a = s / (t*t);
double F = m * a;
double W = F * s;
double x = F + W; //????```

```string dogName = "kula";
Person person;
person.name = dogName;```

```merge [] [] = []
merge [] xs = xs
merge xs [] = xs
merge (x:xs) (y:ys) = if x<y then x:(merge xs (y:ys)) else y:(merge (x:xs) ys)

mergeSort [] = []
mergeSort xs = merge (mergeSort a) (mergeSort b)
where
len = length xs
a = take \$ len `div` 2 \$ xs
b = drop \$ len - len `div` 2 \$ xs```

1. 首先，[]告诉我们，这是一个空列表，但是类型是什么不知道，所以他是forall a –> [a]。所以merge [] [] = []告诉我们，merge的类型至少是[a] –> [b] –> [c]。
2. 其次，merge []  xs = xs告诉我们，merge的类型至少是[d] –> e –> e。这个类型跟[a]->[b]->[c]求一个交集就会得到merge的更准确的类型：[a] –> [b] –> [b]。
3. 然后，merge xs [] = []告诉我们，merge的类型至少是f –> [g] –> f。这个类型跟[a] –> [b] –> [b]求一个交集就会得到merge的更准确的类型：[a] –> [a] –> [a]。
4. 最后看到那个长长的式子，根据一番推导之后，会发现[a]->[a]->[a]就是我们要的最终类型了。
5. 只要把相同的技术放在mergeSort上面，就可以得到mergeSort的类型是[a]->[a]了。

Haskell看完就可以来看C#了。C#的linq真是个好东西啊，只要不把它看成SQL，那很多事情都可以表达的。譬如说是个人都知道的linq to object啦，后面还有linq to xmllinq to sqlreactive programming，甚至是parser combinator等等。一个典型的linq的程序是长这个样子的：

```var w =
from x in xs
from y in ys
from z in zs
select f(x, y, z);```

```W f(X x, Y y, Z z);

var /*IEnumerable<W>*/w =
from /*X*/x in /*IEnumerable<X>*/xs
from /*Y*/y in /*IEnumerable<Y>*/ys
from /*Z*/z in /*IEnumerable<Z>*/zs
select f(x, y, z);

var /*IObservable<W>*/w =
from /*X*/x in /*IObservable<X>*/xs
from /*Y*/y in /*IObservable<Y>*/ys
from /*Z*/z in /*IObservable<Z>*/zs
select f(x, y, z);

var /*IParser<W>*/w =
from /*X*/x in /*IParser<X>*/xs
from /*Y*/y in /*IParser<Y>*/ys
from /*Z*/z in /*IParser<Z>*/zs
select f(x, y, z);```
`var /*IQueryable<W>*/w =    from /*X*/x in /*IQueryable<X>*/xs    from /*Y*/y in /*IQueryable<Y>*/ys    from /*Z*/z in /*IQueryable<Z>*/zs    select f(x, y, z);`
```var /*?<W>*/w =
from /*X*/x in /*?<X>*/xs
from /*Y*/y in /*?<Y>*/ys
from /*Z*/z in /*?<Z>*/zs
select f(x, y, z);```

```var theNumber = (
from n in numbers
group by n into g
select g.ToArray() into gs
order by gs.Length descending
select gs[0]
).First()```

```IParser<FunctionCallExpression> Call()
{
return
from name in PrimitiveExpression()
from _1 in Text("(")
from arguments in
many(
Expression().
Text(",")
)
from _2 in Text(")")
select new FunctionCallExpression
{
Name = name,
Arguments = arguments.ToArray(),
};
}```

`PrimitiveExpression "(" [Expression {"," Expression}] ")"`

posted on 2013-08-17 16:26 陈梓瀚(vczh) 阅读(8386) 评论(16)  编辑 收藏 引用 所属分类: 启示

# re: 如何设计一门语言（九）&mdash;&mdash;类型[未登录] 2013-08-17 16:33 | me

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-18 10:40 | DiryBoy

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-23 17:12 | 42

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-24 16:41 | resty

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-24 21:51 | 陈梓瀚(vczh)
@42

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-24 21:51 | 陈梓瀚(vczh)
@resty

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-25 13:16 | resty
@陈梓瀚(vczh)

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-25 19:57 | AmaF

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-26 11:04 | 陈梓瀚(vczh)
@AmaF

# re: 如何设计一门语言（九）&mdash;&mdash;类型[未登录] 2013-08-26 21:38 | zhaoyg
"C++里面所有中括号不写东西的lambda表达式都可以被转成一个函数指针的"

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-27 00:03 | AmaF
@陈梓瀚(vczh)

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-27 00:58 | 陈梓瀚(vczh)
@AmaF

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-08-27 12:40 | AmaF
@陈梓瀚(vczh)

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-09-16 10:27 | shaoyuan1943

回复  更多评论

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-09-21 10:55 | 大岛小柚子
lambda表达式在C++11就有了，不必等到C++14。

# re: 如何设计一门语言（九）&mdash;&mdash;类型 2013-09-24 10:53 | 陈梓瀚(vczh)
@大岛小柚子
VS2010的lambda的双重this capture有bug，VS2012的lambda还不支持auto类型参数还得写得老长  回复  更多评论