Ocaml 中的module system
来源:互联网 发布:淘宝达人入口网址 编辑:程序博客网 时间:2024/05/21 06:38
文章内容翻译自 manual-ocaml-4.02点击打开链接, 和Ocaml Tutorials其中加入了个人的理解
Modules
基本用法:
Here is the code that we have in our file amodule.ml
:
let hello () = print_endline "Hello"
此句ocaml-top会做这样的提示val hello : unit -> unit = <fun> 表示我们定义了一个函数叫做hello,该函数的输入和输出都是unit
And here is what we have in bmodule.ml
:
Amodule.hello ()
Usually files are compiled one by one, let's do it:
ocamlopt -c amodule.mlocamlopt -c bmodule.mlocamlopt -o hello amodule.cmx bmodule.cmx
现在我们有一个很好的可执行文件用来打印 “Hello”。如你所见,如果你要访问一个给定模块的任何东西,你要用模块的名字(通常是大写字母开头)后面跟一个点号,然后是你要用的东西。可能是一个值,一个类型构造器,或者是给定模块能提供的任何东西。
标准库提供了很多module。比如,List.iter
指定List
模块中的iter
函数。 好了,如果你正在重度使用一个给定的模块,你可以使这个模块的内容直接可以访问。要实现这个,我们要使用open
指令。在我们的例子中,bmodule.ml
可以写成这样:
open Amodule;;hello ();;
很类似java 中的import
注意,人们倾向于避免使用丑陋的“;;”,所以这样写更加普遍:
open Amodulelet () = hello ()
不管怎样,用不用open
是个人品味的问题。一些模块中的命名在很多其他模块中也有。List
模块就是这样的例子。通常我们不用open List
。我们直接写List.XXX 这样可以避免混淆。像Printf
模块,提供通常不冲突的名字,比如printf
。为了避免到处写Printf.printf
,在文件开头放一句open Printf
是有道理的。
有一个简短的例子描述我们刚刚提到的(在toplevel中)。
# open Printf let my_data = [ "a"; "beautiful"; "day" ] let () = List.iter (fun s -> printf "%s\n" s) my_data;;abeautifuldayval my_data : string list = ["a"; "beautiful"; "day"]
Interfaces and signatures 接口和签名(暂时翻译为签名)
一个模块可以给使用它的其他程序提供若干东西(函数,类型,子模块,……)。如果没有什么特别指定,在模块中定义的一切可以从外部访问。这样在小的个人程序中是一般可以的,但是在很多情况下,一个模块只提供它想要给出来的会更好,任何内部使用的辅助的函数和类型我们通常是希望对外面隐藏起来的。*.mli
文件是被导出的模块的签名(signature),猜测这个i表示的是interface,且编译器严格执行它 就拿一个叫Foo
的模块来说, 通常你会有两个文件: foo.ml
和foo.mli
。foo.ml
是实现, foo.mli
是接口或签名.)。它包含了一个值的列表以及他们的类型,以及更多东西。让我们重写amodule.ml
文件。# let message = "Hello" let hello () = print_endline message;;val message : string = "Hello"val hello : unit -> unit = <fun>
因此 Amodule
的接口就是下面这样: 值以及他们的类型,一个字符串,一个函数
val message : stringval hello : unit -> unit
我们现在想把message隐藏起来,可以通过定义一个受限的接口来实现. This is our amodule.mli
file:
val hello : unit -> unit(** Displays a greeting message. *)
(note that it is a good habit to document .mli files, using the format supported by ocamldoc)
.mli 必须在相应的 .ml 文件之前被编译. They are compiled using ocamlc
, even if .ml files are compiled to native code using ocamlopt
:
ocamlc -c amodule.mliocamlopt -c amodule.ml...
----------------------------------------------------------------------------------------------------------------------------------------------------
Abstract types
类型定义是怎么样的呢?我们看到像函数这样的值可以采用把它们的名字和类型放到 .mli 文件的方式来导出。
val hello : unit -> unit
但是模块经常定义新的类型。让我们来定义一个简单的record类型,用来表达一个日期。type关键字用来定义一个新的类型
type date = { day : int; month : int; year : int }
当要写 .mli 文件的时候有四种选择,而不是两种:
- The type is completely omitted from the signature.
- The type definition is copy-pasted into the signature.
- The type is made abstract: only its name is given.
- The record fields are made read-only:
type date = private { ... }
- 类型在签名signature中完全忽略
- 类型定义复制拷贝到签名,也就是说签名中的跟ml中的一样
- 类型做成抽象的:只给出名字
- record的域做成只读的:
type date = private { ... }
In case 3, it would be the following code:
type date
现在,这个模块的用户能操作date
类型的对象,但是他们不能直接访问record的域,他们必须使用模块提供的函数。假设这个模块提供三个函数,一个用来创建一个日期,一个用来计算两个日期之间的间隔,还有一个用年的形式返回一个日期。
type dateval create : ?days:int -> ?months:int -> ?years:int -> unit -> dateval sub : date -> date -> dateval years : date -> float
只有create
和sub
才能用来创建date
record。因此,这个模块的用户不可能创建不规范的record。实际上,我们的实现使用record,但是我们可以修改它,并且确保不破坏任何依赖这个模块的代码!这在一个库中很重要,同一个库之后的版本能够暴露同样的接口,同时可以内部改变实现,包括数据结构。比如我们可以不使用record来实现日期,使用其他的数据结构, 对外面的用户来说你内部如何实现我不关心
- Ocaml 中的module system
- OCaml 中 module 和 Signature 的关系
- ocaml
- OCaml
- OCaml中的 class 和 object
- 使用OCaml的Functor与First class module
- OCaml中的“协变”与“逆变”
- OCaml中的“协变”与“逆变”
- Practical OCaml
- ocaml学习
- ocaml 2
- OCaml安装
- Lmod安装(environment module system )
- Python中的Module
- python中的module
- 编译Android中的module
- .NET中的 Http Module
- flex中的module
- Android中Handler的意义和用法
- Mysql与Oracle区别
- 20150128并查集
- keil编译的CODE.RW.RO.ZI的大小说明
- processAnnotations
- Ocaml 中的module system
- 使用Android studio导入项目
- Android EditText的设置
- iOS拿到推送从而跳转到指定页面
- 必应输入法不争气,自力更生
- 8 Tips To Become A Better Front End Developer
- Oracle、MySql、SQLServer 数据分页查询
- XML笔记
- JDBC连接数据库