论坛首页 综合技术论坛

失踪的链环

浏览 38864 次
锁定老帖子 主题:失踪的链环
该帖已经被评为精华帖
作者 正文
   发表时间:2006-10-08  
charon 写道
但是为什么要从行为区分类型?


也许是说函数类型 (相当于函数签名)?
inc ( N,  1 ) -> N + 1.
那么函数类型就是  int -> int
0 请登录后投票
   发表时间:2006-10-08  
buaawhl同学啊,我这里说的data as procedure和program as data是形而上的适从计算模型上来讨论的,而不是形而下的。因为lambda演算是FP的数学基础,所以FP的程序是可以等价写成lambda计算的。比如

pair(A, B) ->

   fun(select_head) -> A;

      (select_next) -> B end.

实际上是一组函数

pair(x,y) = (λf . f(x, y))
select_head(x) = x . first
select_next(x) = x . last
first(x, y) = x
last(x, y) = y

其对应的lambda演算

Pair1 = pair("god", NextElement)
-> (λf . f("god", NextElement))

    select_head(Pair1)
->  Pair1 . first
->  (λf . f("god", NextElement)). first
->  first("god", NextElement)
->  "god"

这里pair携带数据的根本是,把数据变成函数,也就是data as procedure。

而所谓program as data则是从命令语言的计算模型图灵机入手的,图灵机就是一个大大纸带,然后读指令跟着如操作数,因此数据和代码是没有差别的。为了区分他们,才有了不同的段,或者说结构。




0 请登录后投票
   发表时间:2006-10-08  
buaawhl 写道
charon 写道
但是为什么要从行为区分类型?


也许是说函数类型 (相当于函数签名)?
inc ( N,  1 ) -> N + 1.
那么函数类型就是  int -> int


应该不是,和当时讨论的上下文好像有点差别。OO以后所谓的类型是一个筐子,duck typing中名字的作用比签名/返回值要重要得多(或者说签名的偶然重复性显然要比名字高很多).
而且, int -> int 这个类型也太宽泛了点,只与签名有关,与语义无关。也许会有某些不用不知道,用了下一跳的效果.
0 请登录后投票
   发表时间:2006-10-08  
charon 写道
buaawhl 写道
charon 写道
但是为什么要从行为区分类型?


也许是说函数类型 (相当于函数签名)?
inc ( N,  1 ) -> N + 1.
那么函数类型就是  int -> int


应该不是,和当时讨论的上下文好像有点差别。OO以后所谓的类型是一个筐子,duck typing中名字的作用比签名/返回值要重要得多(或者说签名的偶然重复性显然要比名字高很多).
而且, int -> int 这个类型也太宽泛了点,只与签名有关,与语义无关。也许会有某些不用不知道,用了下一跳的效果.


其实当时我说这个说法是不准确的,应该举个例子来说,比如有一个方法

def printStudent(student)
   put student.name
   put student.age
   put student.grade
end

对应于非duck typing的语言,必须要这样写:

interface Student {
   String name();
   int age();
   String grade();
}

void print(Student s) {
  System.out.println(s.name());
  System.out.println(s.age());
  System.out.println(s.grade());
}

对于duck type,当我增加一个方法
printPerson(person)
  put person.name
  put person.age
end
我可以
student = Student.new("John", 10, "Grade 1")
printStudent(student)
printPerson(student)

这里,对于printPerson方法而言,他需要参数能够相应name和age消息,就可以粗略地认为,这里printPerson需要一个具有name和age方法的类型作为参数,对于这个方法而言,所有具有这两个消息的对象,都是同一类型的。因此,duck typing就是说,因为具有行为,从而显现这个类型的特质。
而反观非duck typing,类型是行为的集合,因为参数是这个类型,所以它具有这样的行为。
0 请登录后投票
   发表时间:2006-10-08  
raimundox 写道
buaawhl同学啊,我这里说的data as procedure和program as data是形而上的适从计算模型上来讨论的,而不是形而下的。因为lambda演算是FP的数学基础,所以FP的程序是可以等价写成lambda计算的。比如

pair(A, B) ->

   fun(select_head) -> A;

      (select_next) -> B end.

实际上是一组函数

pair(x,y) = (λf . f(x, y))
select_head(x) = x . first
select_next(x) = x . last
first(x, y) = x
last(x, y) = y

其对应的lambda演算

Pair1 = pair("god", NextElement)
-> (λf . f("god", NextElement))

    select_head(Pair1)
->  Pair1 . first
->  (λf . f("god", NextElement)). first
->  first("god", NextElement)
->  "god"

这里pair携带数据的根本是,把数据变成函数,也就是data as procedure。

而所谓program as data则是从命令语言的计算模型图灵机入手的,图灵机就是一个大大纸带,然后读指令跟着如操作数,因此数据和代码是没有差别的。为了区分他们,才有了不同的段,或者说结构。


参数 x, y 也是函数?

按照T1的说法,整数可以用函数执行次数来表示。

lambda演算中的任何基本数据(不仅是复合数据结构),也都可以用函数来表示?

比如,负数,小数,字符?
整数和分数,我都看到例子了。
0 请登录后投票
   发表时间:2006-10-08  
引用

这里,对于printPerson方法而言,他需要参数能够相应name和age消息,就可以粗略地认为,这里printPerson需要一个具有name和age方法的类型作为参数,对于这个方法而言,所有具有这两个消息的对象,都是同一类型的。因此,duck typing就是说,因为具有行为,从而显现这个类型的特质。

不是因为具有行为,而是因为具有名字为xxx/yyy的行为,所以显现zzzzzzz
所以这里和是不是具有某种性质的行为是无关的,只是说具有某种名字的行为。
而静态语言的接口,通常会对其方法的语义加以约束(虽然不能从语法上表示出来,但会通过文档等等)
0 请登录后投票
   发表时间:2006-10-08  
FP 没有成员变量。要定义一个数据结构,一般都要用一组 contrustors, selector, operators 函数来表示。

Hash1 = newHashtable(),
Hash2 = put(Hash1, "key", "value" ),
Hash3 = remove(Hash2, "key");

具备了 newHashtable, put, remove 这些函数的数据结构,就可以叫做 hashtable 类型。

印象中,haskell里面的 Num Type 好像是这样定义的。确实需要函数名。支持如下函数,就可以称为 Num。
+ :: a -> a -> a   (可以特化为 int -> int -> int,float -> float -> float )
- :: a -> a -> a   (可以特化为 int -> int -> int, float -> float -> float )
...
等等。
只要有一个数据结构,具备了这些函数定义,就可以叫做 Num 类型。

对 haskell 类型系统不是很熟悉,基本印象如此。

0 请登录后投票
   发表时间:2006-10-08  
charon 写道
引用

这里,对于printPerson方法而言,他需要参数能够相应name和age消息,就可以粗略地认为,这里printPerson需要一个具有name和age方法的类型作为参数,对于这个方法而言,所有具有这两个消息的对象,都是同一类型的。因此,duck typing就是说,因为具有行为,从而显现这个类型的特质。

不是因为具有行为,而是因为具有名字为xxx/yyy的行为,所以显现zzzzzzz
所以这里和是不是具有某种性质的行为是无关的,只是说具有某种名字的行为。
而静态语言的接口,通常会对其方法的语义加以约束(虽然不能从语法上表示出来,但会通过文档等等)

那来的那么罗嗦的事情,duck typing就是一个request/response的过程.走在大街上我见到一个人很像你
于是我叫了一声charon,于是你抛给我一个媚眼.问题是我叫一声猪,你肯定头也不回的往前走.这就是所谓的
"我本将心向明月奈何明月照沟渠"
0 请登录后投票
   发表时间:2006-10-08  
charon 写道

不是因为具有行为,而是因为具有名字为xxx/yyy的行为,所以显现zzzzzzz
所以这里和是不是具有某种性质的行为是无关的,只是说具有某种名字的行为。


你这个从理论上讲是不错的,但是从实际上讲毫无意义。比如我们我有一个方法叫getName(),但是我偏偏要返回年龄,这里无论那种语言都无法解决。这个可以用停机定理来说明,停机是某种特定性质的行为,但是这个是不可用程序判定的。因此,也就是说,无论哪种语言,编译器都无法判定某个方法是否具有特定性质的行为。无论smalltalk,ruby,java或是c++,我们所能依赖的只有名字。

从实际意义来看,在smalltalk,ruby等oo语言里,行为就是相应消息,如果可以相应消息就可以看作具有某种行为。
0 请登录后投票
   发表时间:2006-10-08  
buaawhl 写道


参数 x, y 也是函数?

按照T1的说法,整数可以用函数执行次数来表示。

lambda演算中的任何基本数据(不仅是复合数据结构),也都可以用函数来表示?

比如,负数,小数,字符?
整数和分数,我都看到例子了。


有一个取巧的办法....常数函数。f(x) = 1.1,然后我定义符号1.1就是这个函数...这类常数函数也满足所有的lambda计算...形式上可以得到这个基础函数处理基本数据:
x = f(x) = define(symbol(x), x)
但实际上在实现fp语言的时候,谁也不会做这个东西,都是直接引入literal常量。

而且磐石T1同学说的是丘奇代数....你可以在丘奇数上定义加减乘等运算...丘奇数跟整数还是有差别的...
0 请登录后投票
论坛首页 综合技术版

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