[fp] lich 问你几个fp的问题

simohayha 2007-06-08
haskell里面是不是所有的函数都是lambda实现的?不然为什么

:t 操作符所返回的都是 lambda的表示,也就是说都是用lambda解释的.

呵呵,最好讲下haskell里的type.和java或c里面的不同.

还有在scheme中

((lambda x (+ x 1))2)

要改成
((lambda x (+ (car x) 1))2)
这样的

解释下原因

我知道是把2当成(2)来处理了,我想问这是什么原因.
Lich_Ray 2007-06-08
是。只是语法上不太像。也可以说不是,因为那是lambda的"1.5版"(我的“术语”,Scheme中的是1.0版,学名“一阶lambda演算”)——Curry化算子。Curry化算子认为,一切都是函数(包括普通数据),但如果这个数据的产生式中每一项都是严格的(比如 num = 4 + 3, 3、4都是可以直接推导而不需要进行惰性化的),那么这个数据可以免除其作为函数的义务。对于产生式中有需要推导的数据,Haskell仍将其表示为普通数据(因为类型可以直接推导来确定)。
fact 0 = 1
fact n = n * fact (n-1) -- 这是函数,要推导
num = 5 + fact 4 -- 这个是事实上是函数,但类型上看不出来
另外,之所以haskell中的函数全是lambda的表示,和它的类型系统也有关系。前面说了,Haskell中对函数的理解已经超越了数学映射1.5倍,重点在于对参数列表的理解。数学映射和一阶lambda都认为参数是连续的、一次传递一批,就像Scheme中那样:
(function arg1 arg2)
但Curry化算子认为参数是不连续的、可以分段传递(前提是个数事先固定),每当传递结束而参数不够是,自动转换为一个期待余下参数的函数。这就意味着,如果用Scheme的语法来说明Curry化算子就成了这样:
((+ 1) 2) ;调用一个固定参数个数为两个的函数
这句代码都将行得通!
(map (+ 1) '(1 4 2 5 2))
这对于Scheme来说是非常荒唐的(用宏另当别论),但对于Haskell这是基础:
map (+1) [1, 4, 2, 5, 2]
所以,Haskell的类型系统中对于函数类型的表示才会是那么多个箭头:因为,只要需要推导,就有函数:
Main> :t (+1)
flip (+) 1 :: Num a => a -> a
看出来了吗?不连续的类型导出过程,和java/c等等等等最大的不同点。
至于Haskell类型系统的核心力量——静态多态类型推断,讲起来是在很麻烦。去看中文版的ML语言的书里讲的很详细。

下面那个Scheme的问题跟FP没关系,只是一个语法上的小问题。在Scheme的lambda表达式中,单个参数不带括号即把所有参数当作一个list来处理。不觉得这样写起来很有意思吗?
simohayha 2007-06-08
引用

对于产生式中有需要推导的数据,Haskell仍将其表示为普通数据


这句怎么理解?

Lich_Ray 2007-06-08
只要产生它的表达式中函数调用存在,那么就会被认作函数;但是它的类型只需要一步即可推导,所以Haskell它“看上去”是普通数据。
simohayha 2007-06-08
哦,理解了,谢谢你了.
cookoo 2007-06-13
引用
num = 5 + fact 4 -- 这个是事实上是函数,但类型上看不出来

Haskell是lazy的,所以这么说也不是没有道理,不过这个表达式在编译期肯定被固化成一个值了。
cookoo 2007-06-13
引用
最好讲下haskell里的type.和java或c里面的不同

C和Java的type都是primitive(int之类,没有对象接口)和自定义的结构体或类。

Haskell虽然不是OO语言,没有能保持状态的对象,但是有type class的概念。一个具体的type是type class的实例,将实现type class所定义的接口,比如Int是Num的实例。听上去比较古怪,再想一下就明白Haskell是为了把类型组织成一个层次结构。
simohayha 2007-06-13
昨天晚上把Programming In Haskell  里面那章讲type的,终于对type有点理解了,其实type的基础也就是Currying.

说到class,觉得PIH 里面的解释很好的说:
引用

a  class is a collection of types that support certain overloaded operations called  methods.
cookoo 2007-06-13
我不觉得currying是fp的必要特征,Erlang就没有currying(故意不要的,认为那个容易混淆)。实际来说我觉得默认参数是更可读的方案。
simohayha 2007-06-13
cookoo 写道
引用
最好讲下haskell里的type.和java或c里面的不同

C和Java的type都是primitive(int之类,没有对象接口)和自定义的结构体或类。

Haskell虽然不是OO语言,没有能保持状态的对象,但是有type class的概念。一个具体的type是type class的实例,将实现type class所定义的接口,比如Int是Num的实例。听上去比较古怪,再想一下就明白Haskell是为了把类型组织成一个层次结构。


哦,这下明白了,嘿嘿,谢谢你了.

层次性结构,这也就是sicp里面一直推崇的设计方法.
Global site tag (gtag.js) - Google Analytics