【问题标题】:What is the meaning of `abstract` in the `interface definition`?“接口定义”中的“抽象”是什么意思?
【发布时间】:2013-01-09 12:07:35
【问题描述】:

我完全不明白 interface 在 OCaml 中是如何工作的。

我们来看一个例子:


关于'a

那么'a here 是什么意思?我的意思是我理解在描述函数时,'a 表示arbitrary type。那么这里的意义是什么呢?是arbitrary set的意思吗?

另外,为什么要在set前面加上'a?


摘要

在解释这个例子时,Jason Hickey's Introduction to Objective Caml 说:

我们需要定义一个多态类型的集合'a set abstractly。那 也就是说,在接口中我们将声明一个类型'a set而不给出a 定义,防止程序的其他部分知道,或 取决于我们选择的集合的特定表示。

从上面的陈述中,我猜它的意思是in interface definition, we should hide the implementation details。但是隐藏了哪些细节?


type 'a set = 'a list

在实现文件中,它显示type 'a set = 'a list

那么这有什么作用呢?

是指this set only takes a list吗?如果确实是这个意思,是否有必要在接口文件中说明这一点,因为set 的用户应该知道它只需要列表,对吧?

【问题讨论】:

    标签: functional-programming ocaml


    【解决方案1】:

    那么'a here是什么意思?

    这类似于函数的参数多态性(在 Java 中称为泛型),但对于类型而言。在这个存储整数的代码集中,类型为int set,字符串---string set等。'a在前面,因为它是常见的OCaml语法。在修改后的语法中,类型变量写在类型名之后:如list intset list int。有关不同类型多态性的更多信息,我可以向您推荐一本书Types at programming languages,第五部分:多态性。如果您了解函数的参数多态性,我认为增强您的类型知识并不难。

    隐藏了哪些细节?

    在您的 ML 文件中,'a set 类型定义为元素列表。要搜索列表中的某个元素,必须遍历列表并为每个元素调用(=)(这是List.mem 函数的工作方式)。 AFAIR 在 OCaml 中,stdlib 集合被实现为平衡树,并且存储在集合中的值应该具有函数 compare: t -> t -> int 其中t 是存储在集合中的元素的类型。 但是集合可以有不同的定义,如果你只看 .mli 中的抽象类型,那么你只能猜测它是如何在 .ml 文件中实现的。

    确实,在这个定义中,'a list 类型已经被用来实现'a set 类型,但是从接口文件中,这个信息是不可见的——隐藏的部分是set 类型是真的是list。模块的实现方式以及对外部世界可用的信息的选择,使得程序可以在不知道它是如何制作的情况下使用set 类型。

    这是软件设计的一个重要特性,因为它让开发人员无需更改使用它的代码即可更改该模块的实现。使类型抽象强制分离:如果您尝试在模块外部使用list 作为set,则会收到类型错误。

    type 'a set = 'a list

    AFAIR,这一行引入了一个“类型同义词”(或别名)说:这里和下面的类型 setlist 相同,您可以将 set 与期望 list 的函数一起使用,反之亦然反之亦然。

    当您看到'a set 时,您应该明白它只是一组东西,当您将string 设置为设置时,它将是string set。如果您看到'a set,您无法说出该集合中存储或将存储的内容,但如果您看到string set,您可以。上面的书中也提到了类型同义词。

    附:

    所以你的意思是 type 'a set = 'a list 表示该集合期望列表作为参数?

    不,它没有。您只需在此行中添加新的类型别名。它不会缩小可以替换为 'a 类型变量的类型的数量。如果你写

    # type 'a set = 'a list;;
    type 'a set = 'a list
    # let create x : _ set = [x];;
    val create : 'a -> 'a set = <fun>
    

    然后

    List.map ((+)1) (create 2);;
    

    编译器会将create 2 的类型推断为int set(因为create'a 类型的参数使用了int 值,并且该函数的返回类型为@987654354 @),然后它会查看其类型别名(同义词)表,当它理解类型 set 与类型 list 相同时,它将继续类型推断的过程。

    您应该明白,在创建新同义词时应该编写正确数量的类型变量,即type 'a new_t = ('a*'b) list 对我和编译器都没有任何意义。左边的类型变量应该至少和右边一样多:例如,type ('a, 'b) new_t = ('a * 'b) list 有效。

    【讨论】:

    • u can use set with functions which expect list and vice versa。我完全不明白这一点。所以你的意思是type 'a set = 'a list 表示set 期望list 作为参数?
    • 谢谢。我是新手。你介意告诉我 : _ set 的部分在 let create x : _ set = [x];; 中是什么意思吗?
    • 这是通配符。通常它在模式匹配或类型表达式中很有用(就像这里)。 _ list 表示它是某种东西的列表和这种类型的推理something 我留给编译器。您可以尝试将'a list_ list 之间的区别解释为一个简单的练习,因为现在不想解释它:)
    • In this code sets which store ints will have type int set, strings --- string set etc.。所以'a set 表示这个集合可以存储任意类型。但是如果我写的是map 怎么办?它需要两个参数(键和值),我应该写'a 'a map吗?
    • @JacksonTale 你可以写'a 'b map 或者'k 'v map 或者'key 'value map 以提高可读性——这些类型必须有不同的名字——否则你不能在右边明确地引用它们的定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2011-04-27
    • 1970-01-01
    • 2011-07-05
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多