f# - 如何在 F# 中为 OCaml 中的仿函数编写代码?

标签 f# ocaml functor

我有很多用 OCaml 编写的程序,其中一些使用仿函数。现在,我正在考虑在 F# 中编写和重写部分代码(以利用 OCaml 没有的一些优势)。我害怕的一件事是在 F# 中为仿函数在 OCaml 中所做的事情编写代码。

例如,我们如何模拟 this example from OCaml manual在 F# 中?

type comparison = Less | Equal | Greater

module type ORDERED_TYPE = sig
  type t
  val compare: t -> t -> comparison
end

module Set =
functor (Elt: ORDERED_TYPE) -> struct
    type element = Elt.t
    type set = element list
    let empty = []
    let rec add x s =
      match s with
        [] -> [x]
      | hd::tl ->
         match Elt.compare x hd with
           Equal   -> s         (* x is already in s *)
         | Less    -> x :: s    (* x is smaller than all elements of s *)
         | Greater -> hd :: add x tl
  end

module OrderedString = struct
  type t = string
  let compare x y = if x = y then Equal else if x < y then Less else Greater
end

module OrderedInt = struct
  type t = int
  let compare x y = if x = y then Equal else if x < y then Less else Greater
end

module StringSet = Set(OrderedString)
module IntSet = Set(OrderedInt)

let try1 () = StringSet.add "foo" StringSet.empty
let try2 () = IntSet.add 2 IntSet.empty

最佳答案

这是一种有点不同的方法,它使用泛型类和每个类型一个对象来实现相同的结果。

type Comparison = Less | Equal | Greater

type Set<'a>(compare : 'a -> 'a -> Comparison) =

    member this.Empty : 'a list = []

    member this.Add x s = 
         match s with
         | [] -> [x]
         | hd::tl ->
             match compare x hd with
             | Equal   -> s         (* x is already in s *)
             | Less    -> x :: s    (* x is smaller than all elements of s *)
             | Greater -> hd :: this.Add x tl


let compare x y = if x = y then Equal else if x < y then Less else Greater

let compareFloats (x : float) (y : float) = if x = y then Equal else if x < y then Less else Greater

// Note that same generic compare function can be used for stringSet and intSet
// as long as the type parameter is explicitly given
let stringSet = Set<string>(compare)
let intSet = Set<int>(compare)

// Type parameter not needed, because compareFloats is not generic
let floatSet = Set(compareFloats)

let try1 () = stringSet.Add "foo" stringSet.Empty   // -> ["foo"]
let try2 () = intSet.Add 2 intSet.Empty             // -> [2]
let try3 () = floatSet.Add 3.0 floatSet.Empty       // -> [3.0]

关于f# - 如何在 F# 中为 OCaml 中的仿函数编写代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36847449/

相关文章:

c++ - 将可调用对象传递给成员函数

f# - 如何编写一个函数,该函数返回数组 y 中数组 x 中值的索引数组?

F#:为什么选项类型与可为空类型不兼容?

ocaml - OCaml中类型和模块相等的规则是什么

ocaml - OCaml 中异步调用函数

c++ - 标准::设置。定制套组

c# - 如何使用 F# 处理来自 C# 的列表

list - F# : list. [(参数)..] 匹配模式中的错误

ocaml - 如何使用 Lwt 从特定目录正确启动进程

C++使用仿函数将函数传递给函数