OCaml 仿函数,Haskell 类型 类,和多重推导
OCaml functors, Haskell type classes, and multiple derivation
众所周知,OCaml 具有参数多态性,这会导致一些限制。 Haskell,通过它的类型 类,提供了一个 ad hoc 多态性,这显然在一些情况下非常方便。众所周知,OCaml 的模块和仿函数系统允许创建一种 ad hoc 多态性。例如,参见 Simon Shine here 最近的精彩回答。
我的观点是,在 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
目标是编写一个仿函数F
,由实现Showable
和Readable
的模块参数化。
当然,这实际上很简单,使用模块包含。
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 define its own module type argument. Here is an example with the Kruskal module 中的每个函子。仿函数需要一个 Kruskal.G
类型的模块,它实现了 Sig.G
的子签名(大多数图模块都实现了)。
众所周知,OCaml 具有参数多态性,这会导致一些限制。 Haskell,通过它的类型 类,提供了一个 ad hoc 多态性,这显然在一些情况下非常方便。众所周知,OCaml 的模块和仿函数系统允许创建一种 ad hoc 多态性。例如,参见 Simon Shine here 最近的精彩回答。
我的观点是,在 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
目标是编写一个仿函数F
,由实现Showable
和Readable
的模块参数化。
当然,这实际上很简单,使用模块包含。
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 define its own module type argument. Here is an example with the Kruskal module 中的每个函子。仿函数需要一个 Kruskal.G
类型的模块,它实现了 Sig.G
的子签名(大多数图模块都实现了)。