我正在学习/玩ocaml在顶部。遵循现实世界的ocaml书。
所以我很自然地开始:
open Base;;
接下来我试试:
utop # String.sub "Hello world!" 3 4;;
Line 1, characters 0-10:
Warning 6 [labels-omitted]: labels pos, len were omitted in the application of this function.
Line 1, characters 0-10:
Warning 6 [labels-omitted]: labels pos, len were omitted in the application of this function.
- : string = "lo w"
好吧,和预期的差不多。Base
用使用标记参数的版本取代了许多标准函数,如String.sub
(可以说是一件好事,所以我对此没有任何抱怨)。
但让我困惑的是。当我试图检查改进的String.sub
的签名/类型时,我希望看到一个改进的函数签名类似于"标准"String.sub
签名(string -> int -> int -> string
),但带有标记的参数。我看到的是:
utop # String.sub;;
- : (string, string) Blit.sub = <fun>
那是什么意思?一个(天真的)用户如何使用它来确定调用String.sub
函数的正确方法?
。我怎么从像(string, string) Blit.sub
这样的签名中发现…
- 它是一个函数?
- 它期望什么类型的参数?
- 它期望参数上有什么标签?
- 它返回什么类型的值?
Sub是函数类型的类型别名。但让我们自己去发现吧。我们可以在输出上使用#show
指令来检查它的类型,直到得到满意的结果,
# #show String.sub;;
val sub : (Base.String.t, Base.String.t) Base__.Blit.sub
# #show Base__.Blit.sub;;
type ('src, 'dst) sub = ('src, 'dst) Base__.Blit_intf.sub
# #show Base__.Blit_intf.sub;;
type ('src, 'dst) sub = 'src -> pos:int -> len:int -> 'dst
现在让我们用string
替换'src
和'dst
参数,因为我们有(string, string) sub
,我们得到string的类型。
String.sub : string -> pos:int -> len:int -> string
如果您使用merlin和合适的代码编辑器,则会容易得多。您可以只要求编辑器展开类型,因此需要几毫秒才能到达根目录,Merlin还将为您执行替换。例如,在我的Emacs中,它只是在类型上重复几次C-c C-t
。对于可以通过一次击键轻松导入的文档也是如此(但在本例中不是这样,因为该函数在Base中缺乏文档)。您还可以很容易地跳转到函数的定义或声明。因此,如果你想在OCaml中发挥作用,请考虑设置一个良好的开发环境,如Emacs, Vim, Visual Studio Code或其他。