免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 53457 | 回复: 5
打印 上一主题 下一主题

oCaml的几个问题 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-12-20 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-03-01 09:49 |只看该作者 |倒序浏览
本帖最后由 goingstudy 于 2014-03-01 10:09 编辑

刚开始学函数式编程,可能问的问题比较低级,大婶门不要鄙视我
下面是我看的书上的一个例子,是关于functor的
module type EqualSig = sig
   type t
   val equal : t -> t -> bool
end;;
module MakeSet (Equal :EqualSig) = struct
  open Equal
  type elt = Equal.t
  type t = elt list
  let empty = []
  let mem x s = List.exists (equal x) s
  let add = (::)
  let find x s = List.find (equal x) s
end;;

问题:
1. type t 是什么意思?
2. 下面那部分好像有问题,在ocaml的top level中通不过,貌似是let add = (::)的问题
3. 能给讲讲上面程序的大体意思吗(我能理解个差不多,但还是想听听别人的理解)

论坛徽章:
7
巳蛇
日期:2014-04-10 08:54:57白羊座
日期:2014-04-22 20:06:262015年亚洲杯之沙特阿拉伯
日期:2015-02-10 14:18:532015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之吉达阿赫利
日期:2015-06-02 11:34:112015亚冠之武里南联
日期:2015-06-24 12:13:082015亚冠之阿尔纳斯尔
日期:2015-08-03 09:08:25
2 [报告]
发表于 2014-03-05 01:25 |只看该作者
回复 1# goingstudy

我因为不懂oCaml,所以没打算回的,不过你在另一个帖子中说这个版太冷清了,没人讨论很难进步。出于对函数式编程爱好者的鼓励(我也是函数式编程爱好者加新手了,大家可以一同进步哈哈),我来试着回答你提出的部分问题吧。
虽然我不懂oCaml,但是不管是命令式编程语言还是函数式编程语言,因为都是面向人的编程语言,所以仅从写出的代码片段也可以知道大概的语法结构的作用和代码的意图的,不过没办法判断语法错就是了(特别是在没有错误提示的情况下)。正因为连错误提示都没有,我又不懂oCaml,所以没法回答你的第二个问题。不过,另外两个问题我觉得我都可以给答案,至少正不正确,你得自己去证实。

  1.  type t 的意思是指明 t 是一个类型变量,也就是表示在下面的代码中出现 t 的话,它指的是某个类型 t,只不过具体是什么类型是不确定的,准备来说是可以是任何类型,但是两个 t 至少可以表示是两个变量同类型。
3. 这个代码片段的意思是首先定义了一种类型 EqualSig,这种类型支持一种叫 equal 的方法(也就是函数),这个 equal 方法接受两个相同类型的变量(因为类型均为 t,但是 t 到底是什么不重要,只要类型相同就行),然后返回一个 bool 值,事实上 EqualSig 在Haskell的术语里是定义了一个 type class(因为我懂一点 Haskell 嘛),type class 是相当于面向对象语言里的类的东西,有定义在这种类型上的一系列方法,但是之所以说是相当于,是因为 type class 绝不是面向对象语言里的类,type class 比类要更灵活强大(我自己认为),只是我个人觉得本质上它们还是有些相识的。扯远了,回到后面代码的意思,后面的代码也定义了一个东西,不确定这个定义的是否也是一种类型,还是其他什么的东西,因为定义EqualSig的时候前面有个type关键词,而定义MakeSet的时候没有,不过有一点可以肯定,这个MakeSet,接受一个参数(是的,就算是类型也是可以接受参数的,不光是函数可以接受参数,函数式编程语言就是这么强大这么自然(当然也有很多人说它不自然,不过事实上我认为并不是不自然,仅仅是受限于命令式语言的思维,还没习惯过来而已(我也还没完全习惯过来))),这个参数叫做 Equal,然后是 EqualSig这种类型的。然后接下来就是定义elt也是一个类型变量,这个类型变量只不过是 Equal(也就是EqualSig)里的t的别名而已,而相对的,这里定义了一个新的t,这个t是elt的列表类型,也就是新的t就是老的t的列表类型(复数形式,哈哈),接着定义一系列的变量和函数(函数在函数式编程语言里其实和变量没太大差别,而且说是变量反而还不准确,因为大多数函数式编程语言里我这里用变量指代的东西都是不可变的,这个变量相对命令式编程语言里的变量更接近于数学里变量的概念,数学里的变量的值就是不能随便改变的,如果你令x=5,后面就不能把它变成6),又扯远了,定义的empty就是一个空列表,mem是接受两个参数的函数这个函数判断列表s里是否有元素和x equal,是的,equal,也就是EqualSig 里定义的equal,所以x的类型会和旧的t绑定,从而s就是新的t了,接着定义的add也是一个接受两个参数的函数(因为这个显然是把一个列表连接函数的名字直接赋给了add,也就是说add就是用来把元素添加到列表里去的,或者是连接两个列表的,具体是这两种意思里的哪一种需要查oCaml的语法手册,反正在Haskell里(是用来把元素添加到列表之前的,而(++)是用来连接两个列表的,嗯,大概add多半更可能是Haskell里的(而不是(++)吧,因为(:长得更像(),最后定义的find就是从列表s里查找和x equal的元素的函数了。

好,希望上面的回复对你有点帮助。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-12-20 06:20:00
3 [报告]
发表于 2014-03-05 09:01 |只看该作者
回复 2# Monox
谢谢你详细的回复。
type t,这个明白了,是定义了一个抽象的类型,没有具体化的类型,然后还有一点不明白的地方是你说add 有两个参数,这个从add的功能是如此,但是从定义上是怎么看出来的,貌似函数式编程对参数的个数不是很讲究?只是由解释器推断时来确定?::(两个冒号在ocaml中是添加元素到列表开头,如x ::list), @是链接连个列表

   

论坛徽章:
7
巳蛇
日期:2014-04-10 08:54:57白羊座
日期:2014-04-22 20:06:262015年亚洲杯之沙特阿拉伯
日期:2015-02-10 14:18:532015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之吉达阿赫利
日期:2015-06-02 11:34:112015亚冠之武里南联
日期:2015-06-24 12:13:082015亚冠之阿尔纳斯尔
日期:2015-08-03 09:08:25
4 [报告]
发表于 2014-03-05 10:30 |只看该作者
回复 3# goingstudy

那果然跟我猜测的一样 oCaml 里的 :: 就相当于 Haskell 里的 :,之所以说 add 接受两个参数是因为 add 就是 :: 的别名,而 :: 接受两个参数。oCaml 和 Haskell 一样,在引用用符号表示的函数名的时候需要在函数名前后加上括号。其实我之前回答你的另一个帖子的时候就说了,在函数式编程里事实上函数真正的情况是只接受一个参数,接受多个参数的写法只不过是语法糖而已。然后函数在函数式编程里有curry和partially apply这两种重要的概念,嗯,回答你的这个问题就不扯什么curry和partially apply了,事实上你也可以把 add定义成 let add x xs = x :: xs,这个和 let add x xs = ( :: ) x xs 是完全等价的,而后面这种写法因为等号左右两边最后的部分都一样,所以可以省略成 let add = ( :: ) 这种形式,只不过是语法糖而已,( :: )的类型编译器是知道的(或者是可以推断的),从而 add 的类型(也就是接收几个参数,返回什么类型的结果之类的信息,在 Haskell里就function signature)也是可以推断出来的。Haskell(看来oCaml也是,而像Sheme,Lisp之类的函数式编程语言就不是了)这种强类型的函数式编程语言虽然是类型,也就是必须指定每个变量(包括函数)的类型,但是这里的“指定”并不需要人为显示地在语法层面上指定,这些典型的函数式编程语言都有一个类型推导器的东西,它能推导并确定大多数变量(包括函数)的类型,所以像add后面省略了两个参数,但是oCaml还是可以推导出它的类型是 Equal.t -> t -> t这种形式的,也正因为如此,强类型的编程语言写出来的代码反而没有像C这种类型不强的语言写出来的代码冗长(当然其中还有很多其它原因就是了)。
另外,关于前面重新又提到的函数式编程里的函数事实上只接受一个参数,所以function signature里用来分隔参数和结果类型的分隔符都是 ->,所以 Equal.t -> t ->t其实是 Equal.t -> (t -> t) 这种写法省略了括号而已,而相对的,它和 (Equal.t -> t) -> t 这种类型的函数是不一样的,这种类型的 signature是接收一个类型为(Equal.t -> t)也就是一个函数为参数,并返回t这种类型的结果的函数。嗯,简单一点说,我这里想表达一点的意思是在函数式编程语言里函数和变量在本质上没什么太大的区别,把它们统一对待会比较容易体会函数式编程语言的特点,用法和习惯,诸如此类。
   

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-12-20 06:20:00
5 [报告]
发表于 2014-03-05 11:20 |只看该作者
谢谢,还是有个人能给讲讲理解的快啊

论坛徽章:
7
巳蛇
日期:2014-04-10 08:54:57白羊座
日期:2014-04-22 20:06:262015年亚洲杯之沙特阿拉伯
日期:2015-02-10 14:18:532015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之吉达阿赫利
日期:2015-06-02 11:34:112015亚冠之武里南联
日期:2015-06-24 12:13:082015亚冠之阿尔纳斯尔
日期:2015-08-03 09:08:25
6 [报告]
发表于 2014-03-05 12:28 |只看该作者
本帖最后由 Monox 于 2014-03-05 20:21 编辑

本贴内容删除
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP