2016-06-13 96 views
11

众所周知,OCaml具有参数多态性,这会导致一些限制。 Haskell通过它的类型类提供了一个特别的多态性,这在很多情况下显然非常方便。众所周知,OCaml的模块和函子的系统允许创建一种特设的多态性。例如,请参阅Simon Shine here的最新答案。OCaml函子,Haskell类型类和多重派生

我的观点是,有可能在Haskell中创建类型派生几种类型。例如:

data Person = Person { firstName :: String 
       , lastName :: String 
       , age :: Int 
       } deriving (Eq, Show, Read) 

这是很方便的,以限定具有几个特点(允许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 

目的是通过写一个实现既ShowableReadable模块参数化仿函数F

+2

这必须是我见过的最好的书面问题之一!希望有人能找到答案! – Lhooq

回答

10

当然,这其实很简单,使用模块包含。

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 

破坏性取代在本说明书中的说明:http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234
剩下的就是普通模块的东西(参见手册中的一个完整的解释)

一些仿重型库依靠这种结构亚型的相当很多。例如,ocamlgraph中的每个仿函数都定义了它自己的模块类型参数。以下是Kruskal module的示例。仿函数期望一个Kruskal.G类型的模块,它实现Sig.G的子签名(它由大多数图模块实现)。

+0

谢谢,这其实很简单!从某种意义上说,我们可以说Haskell类型类的系统以及OCaml的模块和函数类的系统是等价的吗? –

+2

它们不相同。正如[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页,了解差异的总结。 –

+3

纠错:比我指出的更聪明的人; Oleg Kiselyov证明了两者之间的等价性(给出了Haskell类型类的过时定义),尽管我找不到这篇文章,而现代Haskell类型类比ML模块更强大,因为它们提供了类型级函数。我会避免做出更大胆的声明,并会回到编写酷的代码片段。 ;-) –