OCaml for Haskellers
来源:互联网 发布:php 记录错误日志 编辑:程序博客网 时间:2024/05/21 09:47
OCaml特有的特性:
- OCaml有命名参数(~x:i 绑定命名参数x的值到i,~x是~x:x的缩写).
- OCaml有可选参数(?(x:i = default)以default为缺省值绑定i到可选命名参数x).
- OCaml有open的联合类型([>'Integer of int|'Real of float])此处类型保留实现; 你可以将其赋值给具有类型'a number = [> 'Integer of int | 'Real of float]as a的类型. 匿名closed联合也是允许的([<'Integer of int|'Real of float]).
- OCaml有可变记录(在定义中preface记录字段可变, 并使用<-操作符赋值).
- OCaml有模块系统.
- OCaml有native对象.
省略部分意味着二者相同(比如, let f x y = x + y)
组织方式:(上一行为Haskell, 下一行为Ocaml)
类型:() Int Float Char String Bool (首字母大写)
unit int float char string bool (小写)
操作符:
== /= .&. .|. xor shiftL shiftR complement
= == != land lor lxor [la]sl [la]sr lnot
(Haskell中,算术还是逻辑移位依赖于Bits的类型.)
OCaml中的俘点操作: 以.为后缀(如+.)
俘点转换:
floor fromIntegral
int_of_float float_of_int
字符串操作:
++ !!i
^ .[i] (注意: 字符串不是字符的列表)
复合类型:
(Int, Int) [Bool]
int * int bool list
列表:
x : [1, 2, 3]
x :: [1; 2; 3]
数据类型:
data Tree a = Node a (Tree a) (Tree a) | Leaf
type 'a tree = Node of 'a * 'a tree * 'a tree | Leaf;;
(注意: 尽管类型参数实际不是tuple, OCaml还是需要用 Node(v,l,r) 做模式匹配)
记录:
data Rec = Rec { x :: Int, y :: Int }
type rec = { x : int; y : int };;
访问字段:
x r
r.x
更新字段:
r { x = 2 }
{ r with x = 2 }
(OCaml records also have destructive update.)
Maybe:
data Maybe a = Just a | Nothing
type 'a option = None | Some of 'a;;
数组:
readArray a i writeArray a i v
[|1; 3|] a.(i) a.(i)<- v
引用:
newIORef writeIORef readIORef
ref := !
全局定义:
x = 1
let x = 1;;
匿名函数:
\x y -> f y x
fun x y -> f y x
递归:
let f x = if x == 0 then 1 else x * f (x-1)
let rec f x = if x == 0 then 1 else x * f (x-1)
Mutual recursion (note that Haskell let is always recursive):
let f x = g x
g x = f x
let rec f x = g x
and g x = f x
模式匹配:
let f 0 = 1
f 1 = 2
let f = function
| 0 -> 1
| 1 -> 2
(note: you can put pattern matches in the arguments for OCaml, but lack of an equational function
definition style makes this not useful)
分支:
case f x of
0 -> 1
y | y > 5 -> 2
y | y == 1 || y == 2 -> y
_ -> -1
match f x with
| 0 -> 1
| y when y > 5 -> 2
| (1 | 2) as y -> y
| _ -> -1
例外:
Definition
data MyException = MyException String
exception MyException of string;;
Throw exception
throw (MyException "error")
raise (MyException "error")
Catch exception
catch expr $ \e -> case e of
x -> result
try expr with
| x -> result
Assertion
assert (f == 1) expr
assert (f == 1); expr
编译:
ghc --make file.hs
ocamlopt -o file file.ml
运行:
runghc file.hs
ocaml file.ml
类型签名. Haskell支持用两个冒号定义表达式的类型. OCaml有两种方式定义类型, 类型声名可以嵌入代码中:
let intEq (x : int) (y : int) : bool = ...
或放入接口文件中(*.mli):
val intEq : int -> int -> bool
Eta expansion. '_a形式的多态类型可以认为像Haskell的monomorphism(单一同态)限制: 仅能被实例化为一具体类型. However, 在Haskell中对于用户不期望的值monomorphism限制用于避免额外的重复计算; OCaml中在面对副作用时,为了保持类型系统的完整,值的限制是需要的, 并且这也适用于函数(仅查找签名中tell-tale '_a). 更基本的,'a意味着一个通用类型, 而'_a意味着一个当时还未知的具体类型 — Haskell中, 所有类型变量都是隐式普遍量化的, 因此前者总是对的(除了monomorphism限制开始生效, 甚至在那时,你也未曾看见任何类型变量. 但OCaml需要monomorphic类型变量防止脱离编译单元, 两者有点相似. 这有意义吗? 别怕.)
Haskell中, 通过定义显示的类型签名,可以使monomorphic值再次polymorphic. OCaml中, 通过eta expanding通用化一个类型. 权威的例子是id函数, 当它以自己为参数时(id id)就产生一个'_a-> '_a类型的函数 (也就是说,被限制了) 。可以通过写一个函数fun x-> id id x来恢复成类型'a-> 'a.
有一个精明的地方处理OCaml的impurity与strictness:eta expansion使用起来就像thunk, 因此如果eta expand的表达式有副作用, 它就会被延迟处理. 当然你可以使用fun ()-> expr来模拟典型的thunk。.
尾递归. 在Haskell中, 当计算是惰性时,你不用担心尾递归; instead你将计算放入一个数据结构中,以便用户不会强制要求超过其需要那么多(被看守的递归), 并且当模式匹配深入到结构中时,栈框架可以被高兴地丢弃. However, 如果你要实现一个类似foldl'这样的严格函数时, 你要注意不要建一个太大的thunk.
OCaml默认是严格的, 因此你总是应该注意尾递归调用. 一个有趣的地方是map函数的实现,其本地版本不能尾递归优化. Haskell中, 由于map是惰性的并且递归隐藏在cons构造子中,这就不是什么问题了; OCaml中, 当获得大列表时,在拷贝整个列表获得TCO或不拷贝而潜在用尽堆栈需要权衡. (注意Haskell中严格的map函数也有同样问题; 这是惰性与严格的区别, 而不是Haskell与OCaml的.)
单个OCaml脚本文件含有按顺序执行的语句列表.(没有main函数).
Haskell的模块对应OCaml的编译单元, 像foo.ml(小写)对应HaskellFoo模块, 或者Foo.foo指Foo中的foo函数.
好的实践是写接口文件(*.mli), 这就像输出列表. 接口文件中也可以有数据定义(忽略构造子来实现隐藏).
缺省时就像引入受限的Foo一样,所有模块是自动"被引入的"(不必有引入列表). 传统的可以使用不受限名字的引入方式在Ocaml中用open Foo实现.
OCaml没有类型类但使用模块能取得一样的效果. (另一个典型的取得类型类效果的方法是使用对象).
- OCaml for Haskellers
- ocaml
- OCaml
- Practical OCaml
- ocaml学习
- ocaml 2
- OCaml安装
- Ocaml 入门整理2
- Ocaml学习笔记 语句
- Ocaml基本认识
- OCaml样本代码
- Ocaml编程速览
- ubuntu ocaml blast
- Ocaml 中的module system
- 学习Ocaml(2)---基础
- 学习ocaml----(3)基础
- Ocaml学习笔记
- ocaml学习随笔-1
- VMware虚拟机中ubuntu安装vmwre tools
- ORA-06553: PLS-213: package STANDARD not accessible
- PID教程
- 电容标称值的表示方法
- VIM编辑二进制文件
- OCaml for Haskellers
- ogre 1.7.3编译
- Java易混淆知识点
- POJ 1679 The Unique MST (次小生成树Prime/Kruskal)
- string int byte转换
- 关于创建和attach设备的一些结构和函数——来自wdk文档(WDK 7600.16385.1)
- 【动规】分类题目列表
- 史上最小的基于IE内核的多标签、多进程浏览器
- MATLAB与自动控制系列教程一: MATLAB建模