OCaml 中的type 数据类型

OCaml 中,你可以自定义type 数据类型,相当于java 的class,或者go 的struct。你可以在一个自定义的数据结构里面存储你的数据结构。

我们看示例

utop # type netrcItem  = {
    Host : string;
    username : string;
    password : string;
};;
Error: Syntax error
utop # type NetrcItem  = {
    host : string;
    username : string;
    password : string;
};;
Error: Syntax error
utop # type netrcItem  = {
    host : string;
    username : string;
    password : string;
};;
type netrcItem = { host : string; username : string; password : string; }
utop # let a = {host: "www.baidu.com"; username: "admin"; password: "admin"};;
Error: Syntax error
utop # let a = {host: "www.baidu.com"; username: "admin"; password: "admin";};;
Error: Syntax error
utop # let a = {host =  "www.baidu.com"; username = "admin"; password = "admin";};;
val a : netrcItem =
  {host = "www.baidu.com"; username = "admin"; password = "admin"}

注意看许许多多的报错提示。为什么会报错。

我们注意到, type 后面跟你定义的 type名称, 名称必须以小写字母开始,你看我输入NetrcItem,它就报错了。

然后type里面的每个属性,都需要用小写字母开头,如果你写成大写,也报错了。

还有,属性和 数据类型之间,用 空格和:符号隔开,记住了,要用空格, 如果你没写空格,也给你报错。

 

我们继续看

utop # let b: netrcItem = {}
;;
Error: Syntax error

utop # let b: netrcItem = {"username" = "nothing"}
;;
Error: Syntax error

utop # let b: netrcItem = {username = "nothing"}
;;
Error: Some record fields are undefined: host password

你不能初始化空属性的数据

你不能用引号把属性名引起来

你不能漏掉属性

你可以用let 表达式定义的时候,用 : netrcItem 制定数据是这个类型。因为OCaml是静态类型的语言。虽然它是有强大的类型系统,可以自己推断,但是我们还是要自己写上类型,这样我们看代码的时候,就知道,原来A是这个类型,B是那个类型。

 

初始化一个type 实例的时候,你需要用 = 号赋值每个属性。如果你不用 = 号,你还是写 : ,也是报错。

 

我们继续看,如果我们定义了两个完全一样的type,但是他们名字不一样,会怎么样。

utop # type bhost = {
host : string;
username : string;
password : string;
};;
type bhost = { host : string; username : string; password : string; }

utop # let c = {host = "localhost", username = " root", password = "admin"};;
Error: This expression has type 'a * 'b * 'c
       but an expression was expected of type string


utop # let c = {host = "localhost"; username = " root"; password = "admin"};;
val c : bhost = {host = "localhost"; username = " root"; password = "admin"}

utop # let c: netrcItem = {host = "localhost"; username = " root"; password = "admin"};;
val c : netrcItem =
  {host = "localhost"; username = " root"; password = "admin"}

例子里面,我们定义了是一个新的bhost的type,看到没有,并不会报错,也就是说OCaml会允许这样的相同的两个结构的 type同时存在。

 

所以为什么我说你let 的时候,要写上类型,因为如果让编译器自己决定,它可能给你错的类型。

 

另外,属性和属性之间,是记得用;分号,不要用, 逗号,如果你之前用其他编程语言,可能会以为是逗号。OCaml 不是这样的。

这个type它还并不是JSON,你不能用逗号【分隔在属性和属性之间】。

 

追加一个功能点,就是元素可以是Optional,可选的数据类型,也就是可以能是Some,也可能是None

有时候有值,有时候没有值

utop # type netrcItem = {host: string option;
username: string option;
password: string option;
};;

type netrcItem = {
  host : string option;
  username : string option;
  password : string option;
}


utop # let a : netrcItem = {host = "localhost"}
;;
Error: This expression has type string but an expression was expected of type
         string option


utop # let a : netrcItem = {host = Some "localhost"}
;;
Error: Some record fields are undefined: username password


utop # let a : netrcItem = {host = Some "localhost"; username = None; password = None;};;
;;
val a : netrcItem = {host = Some "localhost"; username = None; password = None}

分类: 默认 标签: 发布于: 2022-06-27 16:40:29, 更新于: 2022-06-28 10:21:41