OCaml仿函数,Haskell类型类和多个派生

Sam*_*udo 13 ocaml haskell functional-programming caml functor

众所周知,OCaml具有参数多态性,这导致一些限制.Haskell通过其类型类提供了一种特殊的多态性,在很多情况下显然非常方便.众所周知,OCaml的模块和仿函数系统允许创建一种特殊的多态性.看人妖的伟大最近的答案闪耀这里的实例.

我的观点是,在Haskell中可以创建派生多个类型类的类型.例如 :

data Person = Person { firstName :: String
                 , lastName :: String
                 , age :: Int
                 } deriving (Eq, Show, Read)
Run Code Online (Sandbox Code Playgroud)

定义具有多个功能的类型非常方便(允许类型的值Person支持相等性测试,可打印,并且在给定示例中可读).

我的问题如下:我们可以在OCaml中做同样的事吗?通过简单的我的意思是与语言的地面语法和没有太多的计谋.

举一个具体的例子,假设我们有两个OCaml签名

module type Showable = sig
    type t
    val to_string : t -> string
end

module type Readable = sig
    type t
    val from_string : string -> t
end
Run Code Online (Sandbox Code Playgroud)

的目的是写入一个算符F由它实现两者模块参数化ShowableReadable.

Dru*_*rup 12

当然,这实际上非常简单,使用模块包含.

module type S = sig
  include Showable
  include Readable with type t := t (* destructive substitution *)
end

module F ( M : S ) = struct
  let fake_id x = M.from_string @@ M.to_string x
end
Run Code Online (Sandbox Code Playgroud)

手册中解释了破坏性替换:http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234
其余的是常规模块内容(有关完整说明,请参阅手册)

一些算函重型库非常依赖于这种结构子类型.例如,ocamlgraph中的每个仿函数定义了自己的模块类型参数.以下是Kruskal模块的示例.Kruskal.G仿函数期望一个类型的模块,它实现了一个子签名Sig.G(由大多数图形模块实现).

  • 更正:比我更聪明的人指出; Oleg Kiselyov证明了两者之间的等价性(给出了Haskell类型类的一些过时定义),虽然我找不到这篇文章,而现代Haskell类型类比ML模块强,因为它们提供类型级函数.我将避免做出任何更大胆的陈述,并将回到编写酷代码片段.;-) (3认同)
  • 他们不等同.如[Modular Type Classes](http://www.cse.unsw.edu.au/~chak/papers/mtc-popl.pdf)中所述,ML的模块系统比Haskell的类型类更灵活和通用,但是不要不允许递归.组合它们意味着您不必手动编写仿函数应用程序,但您也避免了Haskell每个类型只有一个导入类型类实例的问题.参见Stefan Wehr的[ML模块和Haskell类型类:建设性比较](http://www.stefanwehr.de/publications/Wehr_ML_modules_and_Haskell_type_classes.pdf)第107-110页,了解差异的摘要. (2认同)
  • 这里:[适用半透明函子在Haskell(2004)](https://mail.haskell.org/pipermail/haskell/2004-September/014515.html)由Oleg Kiselyov和Chung-chieh Shan撰写. (2认同)