Skip to content

Commit c78a28e

Browse files
author
ictar
committed
add translations of pycoder weekly #212
1 parent 3b60710 commit c78a28e

10 files changed

Lines changed: 798 additions & 899 deletions

Django/Scalable and resilient Django with Kubernetes.md

Lines changed: 94 additions & 198 deletions
Large diffs are not rendered by default.

Others/Getting Started with Behavior Testing in Python with Behave.md

Lines changed: 0 additions & 471 deletions
This file was deleted.

Others/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,17 @@
7171
- [RPython的魔力](./RPython的魔力.md)
7272

7373
RPython是个翻译器,一个编译时运行的翻译器。本文关注与RPython本身,主要说明了其特性及相关错误。
74+
75+
- Henry Kupty的函数式编程扫盲系列
76+
77+
- [了解函数式编程背后的属性:单子(Monad)](./了解函数式编程背后的属性:单子(Monad).md)
78+
79+
本文讲解了函数式编程中的单子,及其三大法则。
80+
81+
- [在Python中使用Behave来开始行为测试](./在Python中使用Behave来开始行为测试.md)
82+
83+
本文通过讲述一个21点的例子,借助Python中的Behave库,带你体验什么是BDD,行为驱动开发。
84+
85+
- [使用gdb调试CPython进程](./使用gdb调试CPython进程.md)
86+
87+
想在不重启应用的情况下调试CPython应用?此时pdb可无用武之地哦~ 所以,试试gdb吧!

Others/Understanding the Math behind FP

Whitespace-only changes.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
原文:[Understanding the Math behind FP: The Monads](http://hkupty.github.io/2016/Understanding-the-math-behind-fp-monads/)
2+
3+
---
4+
5+
在我[之前的文章中](http://hkupty.github.io/2016/Functional-Programming-Concepts-Idioms-and-Philosophy/)(Ele注:这个之前也翻过,地址是[函数式编程:概念,惯用语和理念](./函数式编程:概念,惯用语和理念.md)),我谈了一些关于函数式编程的东西,希望将其介绍给那些之前没有函数式编程经历的新手和开发者。
6+
7+
一些人说它不是非常精确的,并且它并没有解释一些细节所需水平的概念(例如,单子(Monad)或函子(Functor))。好吧,我真的希望在这篇文中能够说明这些细节。尽管如此,我还是会尽量使得它对于那些之前从未进行函数式编程的人来说,是轻量的。
8+
9+
与前面提到的一篇博文一起,我希望让更多的人对函数式编程的概念以及它们如何被应用在“非函数式”语言上感兴趣。我坚持从特定的语言中分离函数式编程的概念,因为它大部分的概念可以(有时作为最佳实践被强制)用于任何语言。
10+
11+
我将写一系列的文章来解释结构,从今天的单子(Monad)开始,并将尝试在一个非函数式语言上导入(或实现)它们。
12+
13+
我将在scala中解释这些结构,并且编写Python代码作为在其他语言中等价性的证明。我不希望这些Python代码成为生产类,而是希望它们是学习函数式编程的工具。
14+
15+
另外,如果你想要看看这些概念在其他语言中是什么样子,或者对于下一个主题有什么想法,不要犹豫,请告诉我。
16+
17+
## 单子(Monad)和它们的法则
18+
19+
如前面所解释的,单子(Monad)是容器。对于面向对象开发者来说,它们看起来非常像[范型](https://docs.oracle.com/javase/tutorial/extra/generics/)。事实上,它们是范型的一个带有[具体法则](https://wiki.haskell.org/Monad_laws)的更为特殊的版本。这些法则存在,以允许你在和单子(Monad)打交道的时候,可以总是期待相同的行为:
20+
21+
* 左单位元(Left Identity);
22+
* 右单位元(Right Identity);
23+
* 关联性
24+
25+
在解释该法则之前,我还会定义类型必须是一个单子的一组操作,使用额外的通用签名,使用`arguments -> return`:
26+
27+
* 返回(return) `a -> M[a]`;
28+
* 绑定(bind)函数 `(M[a], a -> M[b]) -> M[b]`
29+
30+
虽然类型构造和返回函数似乎很明显,但是绑定函数(在scala中,称为`flatMap`)需要一点解释:这是一个接受用`a`创建的单子的函数,以及一个接受`a`和返回用`b`创建的单子来返回用`b`创建的单子(原文是:It is a function that takes a Monad of `a`, and a function that takes `a` and returns a Monad of `b` to return a Monad of `b`)。
31+
32+
这可以如下在代码中写成:
33+
```
34+
val m: List[Int] = List(12, 34)
35+
// m is our Monad, bein List a monadic type
36+
37+
val n = m flatMap (i => i.toString)
38+
// toString is an operation that returns a String, which can be also read as a list of characters
39+
40+
n == List[Char]('1', '2', '3', '4')
41+
```
42+
43+
为嘛?该函数接受一个Int并返回一个String(字符表),它符合上面定义的`bind`签名。它接受一个值(列表中的第n个位置)和一个接受该值的函数,并用所提供函数的结果生成一个单子(与我们使用的单子相同的类型)。
44+
45+
有了这个解释,让我们继续讲法则:
46+
47+
### 左单位元(Left Identity)
48+
49+
该法则规定,`(return a) bind f == f a`或者`用'a'创建一个单子并用'f'绑定,与调用'f(a)'相同`
50+
51+
我们可以证明这个法则:
52+
```
53+
def toListString: Int => List[String] = i => List(i.toString)
54+
55+
val leftProperty = List(1) flatMap (toListString)
56+
val rightProperty = toListString(1)
57+
58+
leftProperty == rightProperty
59+
```
60+
61+
### 右单位元(Right Identity)
62+
63+
该法则规定,`m bind return == m`或者`在一个单子上绑定return返回相同的单子`
64+
65+
我们可以证明这个法则:
66+
```
67+
val monad = List(1)
68+
69+
val boundValue = monad flatMap (List(_))
70+
71+
boundValue == monad
72+
```
73+
74+
### 关联性
75+
76+
该法则规定,`m bind f bind g == m bind (i -> f(i) bind g)`或者`绑定f到一个单子,然后绑定g,与绑定一个函数(这个函数使用f生成一个单子然后绑定g到这个单子)到相同的单子相同`
77+
78+
它也许听起来有点复杂,但是我们可以证明这个法则:
79+
```
80+
def double(i: Int): List[Int] = List(i * 2)
81+
def triple(i: Int): List[Int] = List(i * 3)
82+
83+
val monad = List(1)
84+
85+
val leftProperty = monad flatMap double flatMap triple
86+
val rightProperty = monad flatMap {i => double(i) flatMap triple}
87+
88+
leftProperty == rightProperty
89+
```
90+
91+
## 你在Python中的第一个单子(Monad)
92+
93+
下面,我在Python中定义了Monad类,暴露了上面定义的法则,以及一些使用样例。
94+
```py
95+
## Monad
96+
class Monad(object):
97+
98+
"""A Monadic container in python."""
99+
100+
def __init__(self, containedValue):
101+
"""init is our 'return' function here."""
102+
self.__value = containedValue
103+
104+
def flat_map(self, f):
105+
return f(self.__value)
106+
107+
# Overriding '==' so we can prove the laws
108+
def __eq__(self, o):
109+
return isinstance(o, type(self)) and o.__value == self.__value
110+
111+
def __repr__(self):
112+
return "{}({})".format(self.__class__.__name__, self.__value)
113+
114+
## Helper functions
115+
116+
def to_monad(i):
117+
return Monad(i)
118+
119+
def to_doubled_monad(i):
120+
return Monad(i * 2)
121+
122+
## Proving the laws
123+
# Left Identity
124+
Monad(1).flat_map(to_doubled_monad) == to_doubled_monad(1)
125+
Monad("something").flat_map(to_doubled_monad) == to_doubled_monad("something")
126+
127+
# Right Identity
128+
m = Monad(1)
129+
m == m.flat_map(lambda k: Monad(k))
130+
131+
m2 = to_monad({1: 2})
132+
m2 == m2.flat_map(to_monad)
133+
134+
# Associativity
135+
m = Monad(1)
136+
left = m.flat_map(to_monad).flat_map(to_doubled_monad)
137+
right = m.flat_map(lambda k: to_monad(k).flat_map(to_doubled_monad))
138+
```
139+
140+
## 你在Python中的第二个单子(Monad)
141+
142+
正如上面的例子所描述的,`Monad`类型并未做什么特别的事,它只是像一个容器一样,包装实际的值。可以创建一些从Monad继承的有意义的类,例如下面的Try Monad:
143+
```py
144+
class Try(Monad):
145+
146+
class Success(Monad):
147+
pass
148+
149+
class Failure(Monad):
150+
pass
151+
152+
def flat_map(self, f):
153+
try:
154+
return super(Try, self).flat_map(f)
155+
except Exception as e:
156+
return Try.Failure(e)
157+
```
158+
159+
请注意,这个实现是基本的,并缺乏类型正确性,但是它对我们探索单子法则仍旧足够有趣。
160+
161+
## 总结
162+
163+
我知道我们还缺少一些重要的答案,如“为什么我需要一个单子”和“我怎么使用这一切来工作”,但是再一次说明,这是一个关于函数式编程的系列文章的第一篇(实际上是第二篇),它具有唯一目的,即向那些对函数式编程有兴趣,但觉得它是非常复杂,或可能并不需要它的人阐明函数式编程。
164+
165+
我会再写一些文章,涵盖其他与函数式编程密切相关的数学主题,例如函子(Functor),Monoid,加强版函子(Applicative)。因为我有我的ISP的问题,所以我可能会推迟这写文章,因此,如果你渴望了解更多,我在推荐优秀的[为了更大的好处,学些Haskell](http://learnyouahaskell.com/a-fistful-of-monads)
166+
167+
我希望你喜欢这篇文章,但如果你不喜欢(或不同意)我写的东西,那么随意在tweet上告诉我或发送电子邮件给我。
168+
169+
:x

0 commit comments

Comments
 (0)