论坛首页 综合技术论坛

回albertLee:关于Category Theory 和Monad

浏览 23776 次
该帖已经被评为精华帖
作者 正文
   发表时间:2007-12-15  
canonical 写道
其实我的问题是除了那些别人已经明确写下的,与函数式明显相关的例子,有没有人能够独立的想象到monad的形象,并在非函数式语言中找到类似的应用效果。parsec显然还是函数式内部的例子。这当然不用思考,因为haskell的核心部分就包含了monad.

关于数学学习的一个问题就在于,很多人只能在原始的语境下通过书本已经明确阐明的思维线索来做表面的理解。这样并得不到真正的知识,因为你并没有具有把它应用到其他未阐明的情形下的能力。

饿的rparsec, jparsec都有return, seq, bind, plus啊。
0 请登录后投票
   发表时间:2007-12-15  
我看过你的jparsec, 不过在我看来它还是函数式形式下的一种表达。比如我需要回答几个问题:
1. 具体什么特征使得imperative风格所要求的调用顺序在纯粹的函数式语言中成为可能。
2. 如果在某些情况下monad能够简化编程,它的依据是什么。
3. 副作用如何借助monad进入函数式语言,并确保它不会影响到语言的其他部分。
4. monad的每个条件能否独立进行直观理解,而不是把它们看作一个完整的不可破的数学整体。
5. 除了已经熟知的例子之外,能否想到别的。

我举一个例子:
在jsp中可以使用弱类型的EL表达式,在其中可以使用复合属性
x.y.z.t。在java中每个返回的属性都可能是null, 因此在调用的时候需要做判断,但是在EL表达式中我们内置一条运算规则,null指针上调用任何函数都返回null,这样我们就可以不再通过嵌套判断来进行演算,在形式上回归到stream style.
0 请登录后投票
   发表时间:2007-12-17  
我实在愚笨,看不懂canonical想表达什么。
0 请登录后投票
   发表时间:2007-12-17  
大家都知道monad要满足几个数学条件,我的问题其实很简单,为什么要满足这几个条件,不满足其中一条有什么样的影响。你可能会回答说,不满足条件就不构成monad. 这不是回答,因为我们所需要的不是monad,而是monad带给我们的价值。为什么不满足某个条件就无法产生这种价值? 你可能会说,不满足这几个条件monad就没有那么良好的数学性质,就不能参与combination等。但是你在说到所谓的数学性质的时候,你的脑海中是否适时呈现出什么具体的场景,其中使得这些条件的存在性成为必然的需要? 很多时候我们说到数学的时候,不过是复述书本的陈述,自己并没有真正感觉到其中的真理的存在。

除了那些在书本上已经举过的例子之外,是否能够发现不那么常见的应用。即使它只是平凡的,直接的应用,自己发现它也比复现书本上的繁复例子要有意义的多。
0 请登录后投票
   发表时间:2007-12-17  
请楼上同学不要把其他帖子的讨论带到这里来。你完全可以在原先的帖子里面继续。
0 请登录后投票
   发表时间:2007-12-17  
canonical 写道
大家都知道monad要满足几个数学条件,我的问题其实很简单,为什么要满足这几个条件,不满足其中一条有什么样的影响。你可能会回答说,不满足条件就不构成monad. 这不是回答,因为我们所需要的不是monad,而是monad带给我们的价值。为什么不满足某个条件就无法产生这种价值? 你可能会说,不满足这几个条件monad就没有那么良好的数学性质,就不能参与combination等。但是你在说到所谓的数学性质的时候,你的脑海中是否适时呈现出什么具体的场景,其中使得这些条件的存在性成为必然的需要? 很多时候我们说到数学的时候,不过是复述书本的陈述,自己并没有真正感觉到其中的真理的存在。

除了那些在书本上已经举过的例子之外,是否能够发现不那么常见的应用。即使它只是平凡的,直接的应用,自己发现它也比复现书本上的繁复例子要有意义的多。


Monad的之所以要满足这些数学约束,是以因为它本身是给编译器提供一种约束规范和类型理论。你可说搞得那么tricky,有必要吗?的确没必要,return,>>=,zero,plus,本身就是数学意味太浓只适合给机器看,所以才搞出do语句模仿人类熟悉的语言。甚至你可以不考虑Monad语法和数学背景,用物理学哲学的whatever什么样的观点去类似的平凡的,常见的,具体的应用.但是可惜的是到目前为止人类的计算机技术比起火星人的还是太白痴,如果你不给这些语言里加上数学的机械语义那么正确性只能靠人肉保证,unit test,continuous integration whatever.
所以简而言之,Monad以及任何涉及计算机技术的数学语言都是为了给编译器或者其他机器程序指定的规则以便解放人肉工作.因此数学给于我们的是确定性和能行性,剩下的就要看人类的艺术能力.
转一把G9老大的Blog赫赫:
引用
这好比20年前Wolfman的Mathematica搞定自动积分,号称机器不能积的,人肉也不用想。又好比优化编译器生成人肉编译器们望尘莫及的全局优化代码。众多老大多年积累引为自豪的技巧转眼成为自娱自乐的玩具,价值可比1949年太祖登位前的法币。技巧贬值事小,附着于技巧上的汗水,骄傲,地位,以及掌控未来的安全感也烟消云散恐怕更有杀伤力。所以愤怒和抵制情绪就象巴普洛夫狗的唾液一样自然分泌。一将功成万骨枯。世界就这么残酷。工业革命萌芽时疯狂打砸自动纺织机器的英国纺织工人们想必早有体会。历史上喜剧也总在重演。我们至少已经看过机器语言高手们对汇编的鄙视,汇编语言高手们对C的不屑,C语言高手们对使用垃圾收集器的愤怒.


所以还是高爷爷说的好:"Science is what we understand well enough to explain to a computer. Art is everything else we do.... Science advances whenever an Art becomes a Science. And the state of the Art advances too, because people always leap into new territory once they have understood more about the old."
0 请登录后投票
   发表时间:2007-12-17  
Monad满足任何约束,仍然需要我们去理解它。所以我的问题就是如何直观的去理解。

举个例子,hashkell里应用monad的一个作用是引入imperative风格。但是这里的基本原理在于函数复合自然保证了序关系 f(g(h(x))).

Landin在1965年就在应用这一方式,它和monad概念本身并没有什么必然的关系.

一个现实中的例子: 在前台js中我们需要进行多个异步ajax调用,本质上异步调用可以是并发进行的(与函数式语言中函数的运算场景类似),但是我现在要求对多次ajax调用增加一个顺序约束,即要求它们按顺序调用, 如何提供一个合适的封装形式? 它的实现结构是怎样的?
  ajaxCallA -> ajaxCallB -> ajaxCallCallC
0 请登录后投票
   发表时间:2007-12-18  
Monad理解为声明Monad定义所包含的高阶函数作用于某一Class所参与的计算过程?
0 请登录后投票
   发表时间:2007-12-18  
canonical 写道
Monad满足任何约束,仍然需要我们去理解它。所以我的问题就是如何直观的去理解。

举个例子,hashkell里应用monad的一个作用是引入imperative风格。但是这里的基本原理在于函数复合自然保证了序关系 f(g(h(x))).

Landin在1965年就在应用这一方式,它和monad概念本身并没有什么必然的关系.

一个现实中的例子: 在前台js中我们需要进行多个异步ajax调用,本质上异步调用可以是并发进行的(与函数式语言中函数的运算场景类似),但是我现在要求对多次ajax调用增加一个顺序约束,即要求它们按顺序调用, 如何提供一个合适的封装形式? 它的实现结构是怎样的?
  ajaxCallA -> ajaxCallB -> ajaxCallCallC


实际上吧,我一开始觉得你可能是表达能力不是太好,写的东西别人不容易懂。现在看来,我觉得你首先是对知识的理解上模棱两可,含混不清.
第一,monad的目的的确是为了引入副作用.但是副作用是因为出现不能保证序关系的操作吗?显然不是.
第二,Landin 65描述的general jump and label是为了保证序关系吗?也显然不是,landin 65实现的J operator的目的实则上就是现在lisp上call/cc的一个初级版本,实际上就是一个Continuations.Landin的目的是用它来对应Algo 60的goto.Continuations是可以作为Stack Frame的替代品.就Dijkstra 68'的观点来说,这种方式实则是破坏程序的执行顺序。当然在函数式语言来说,由于没有side-effection,所以Continuations与goto比起来不会有那么大的破坏性。而且Continuations足够powerul,强大到可以突破原来的无并发程序的顺序性来模拟并发.
Code:Producer ( c ):
  Loop:
    Produce;
    CallCC c

Consumer( p ):
  Loop:
    Consume;
    Callcc p
这样的结构称得上顺序约束吗?当然你要说,你的顺序是指的并发同步后的顺序,那就是另外的话题。
第三,我不否认Monad当中的一大部分实际上就是一个Continuations。这也是Monad实现的根本。但是我们要知道,Monad出现之前,Lisp的程序员就把Continuations当做家常便饭来玩了。如果Continuations能够玩的不错,还需要费那么老牛鼻子劲去搞外星人才看得懂的Monad吗?Monad出现是为什么?实则上我在文章中剖析的非常清楚,就是为了回答什么是同类型或者说什么叫做"共同性"。回答这个问题需要引入Monad,在普通的Continuations对参与运算的函数的类型是不关心的.另外一方面,即便f,g,h的都是同样的类型,但是他们的复合却不一定是同样的类型。比如f:a->sqrt(a),g:a->a*-1,那么f和g从类型上来说他们都是int->int,但是他们的复合就是int-complex.Monad需要解决的就是这样两个的问题---那些函数的是具有这些共同性的,那些函数没有;具有共同性若干个函数经过复合以后是否还能保持相同的类型,也就是我们说的是否能保持共同性.

为什么要保持这种共同性呢?从引入impretive语言角度来说(虽然这并非是引入Moand的唯一原因)是因为我们无法避免并发,所以我们也无法避免出现副作用。f g h只要有一个函数如果是有副作用的,那么复合函数就会有副作用。由于functional programming讲究的就是high order的函数复合。如果一大堆的函数复合里某一个带副作用的函数出现了无法预料的值,那么对整个函数里进行凑丝剥茧的调试和测试就要靠人肉debug,人肉unit test。因此Monad对于类型,就如GC对于内存管理,GC出现了是为了解放程序员在内存异常的调试上的人肉工作,Monad的出现就是为了解放程序员在类型异常上调试的人肉工作。有了Monad,它就能规定编译器,一个IO Monad只能复合IO操作,而不能复合其他非IO操作,如果复合了那么编译器就报错。这样IO操作带来的副作用问题,就给IO Monad限定在一个范围以内,而不会四处乱窜。一旦你这个IO Monad里面出现了意料之外的值,那么这个破坏性最多只会破坏IO Monad本身并返回一个failure, 或者根本不返回值,于是这些破坏性就不会波及到程序的其他部分.这才是的函数式语言"引入的imperative风格"过程中Monad需要解决的真正问题,而不是通过什么函数复合来保证序关系。

总的来说,Monad谈论的是类型的复合而不是函数的复合,没有类型系统就谈不上共同性,Monad只有在Typed-lambda calculus上才有意义。如果在没有类型的DuckTyping系统上,那么所有东西的类型都是一样的,Typed-lambda calculus的运算就会退化为lambda calculus运算,取消了类型那么"同类型"的函数的复合就会退化成一个Continuations.从这个角度来说,Continuations可以说是Monad的一种特例,就如同二维坐标是三维坐标的特例一样.你可以说Continuations满足的特性,Monad同样满足。但是你不能反过来说,因为在Typed-lambda calculus上类型的运算遵循着一些与函数运算不一样的法则。我们更不能说,因为Continuations可以保证运算的序关系而且Monad也能保证运算的序关系,所以只要研究了Continuations的所有特性,那么就等于研究了Monad的所有特性。正如我们可以说,三维坐标上的加减乘除与二维坐标上的一致,但是你不能根据这个理由推出,二维坐标上的微分运算法则与三维坐标上的一致.









0 请登录后投票
   发表时间:2007-12-18  
canonical 写道
大家都知道monad要满足几个数学条件,我的问题其实很简单,为什么要满足这几个条件,不满足其中一条有什么样的影响。你可能会回答说,不满足条件就不构成monad. 这不是回答,因为我们所需要的不是monad,而是monad带给我们的价值。为什么不满足某个条件就无法产生这种价值? 你可能会说,不满足这几个条件monad就没有那么良好的数学性质,就不能参与combination等。但是你在说到所谓的数学性质的时候,你的脑海中是否适时呈现出什么具体的场景,其中使得这些条件的存在性成为必然的需要? 很多时候我们说到数学的时候,不过是复述书本的陈述,自己并没有真正感觉到其中的真理的存在。

除了那些在书本上已经举过的例子之外,是否能够发现不那么常见的应用。即使它只是平凡的,直接的应用,自己发现它也比复现书本上的繁复例子要有意义的多。

你的这番话其实这也正是我想说的,希望你在你的关于程序结构的文章中给出的东西,而你没有给出。不管是10个线程,还是extends算子,你给出的东西都不足够充分,不够深入具体。真想对你说,别整那些没用的了,来点真格的吧。
我不应该在这个帖子里谈那个帖子,不过canonical同学的这段话真是说到我心里去了,所以不得不发。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics