与OCaskl中Haskell的类型类最接近的是什么?

Jas*_*Yeo 42 polymorphism ocaml haskell typeclass

有什么方法可以完成Haskell的类型类在OCaml中的作用?基本上,我想编写一个多态函数而不需要编写太多代码.进行多态的典型方法是提供一个额外的参数,告诉函数它当前正在处理什么类型.例如,假设我要对一个int列表进行排序,我必须将另一个比较器传递给该函数.

type comparison = Lesser | Equal | Greater

my_sort : (a' -> a' -> comparison) -> 'a list -> 'a list
Run Code Online (Sandbox Code Playgroud)

反正有没有告诉OCaml我的类型是可比较的,而不是为我想要排序的每种类型编写比较器函数?这意味着我的排序功能看起来像这样:

my_sort : 'a list -> 'a list
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 26

这真的取决于你想要达到的目标.

如果您对OCaml多态比较函数(它不适用于循环和函数值)感到满意,您可以简单地写:

let my_sort l = List.sort Pervasives.compare l
Run Code Online (Sandbox Code Playgroud)

模仿类型类的更通用的方法是使用仿函数:

module type COMPARABLE = sig
  type t
  val compare: t -> t -> int
end

module MySort (C: COMPARABLE) = struct
  let sort l = List.sort C.compare l
end

(* You can now use instantiate the functor *)
module IntAscending = struct
  type t = int
  let compare = (-)
end
module IntDescending = struct
  type t = int
  let compare x y = y - x (* Reverse order *)
end

module SortAsc = MySort(IntAscending)
module SortDesc = MySort(IntDescending)
Run Code Online (Sandbox Code Playgroud)

  • 有趣.Haskell中的类型可以派生出几个类型类(例如,对于既可显示又可读的类型).OCaml模块和/或仿函数可以模拟这个吗? (2认同)

And*_*uer 24

这在Derek Dreyer,Robert Harper和Manuel MT Chakravarty的" Modular Type Classes " 中有详细解释.在第34届ACM SIGPLAN会议论文集 - SIGP编程语言原理研讨会上,ACM出版社,2007年.摘自:

事实证明,ML模块和Haskell类型类是程序结构的高效工具.模块强调程序组件的显式配置和数据抽象的使用.类型类强调隐式程序构造和ad hoc多态.在本文中,我们展示了如何通过将类型类视为模块的特定使用模式,在显式类型模块语言的框架内支持类型类编程的隐式类型样式.此视图提供了模块和类型类的和谐集成,其中类型类功能(如类层次结构和关联类型)自然地作为现有模块语言结构(如模块层次结构和类型组件)的使用而出现.此外,程序员可以明确控制哪些类型类实例可供给定范围内的类型推断使用.我们将我们的方法形式化为Harper-Stone风格的细化关系,并提供声音类型推理算法作为实现的指南.

  • 另请参阅 White 和 Bour 的“[Modular Implicits](http://www.lpw25.net/ml2014.pdf)”论文(引用该论文作为灵感)。 (2认同)

new*_*cct 12

我碰到一个非常好的文章展示OCaml中Haskell中类型和类型类和模块和模块类型之间的转换传来:http://conway.rutgers.edu/~ccshan/wiki/blog/posts/Translations/

基本上,正如@Thomas所示,Haskell中的类型类成为OCaml中的模块类型,具有类型(实现类型类的类型)和使用该类型的一堆值.

然后,对应于Haskell中类型类的"实例",您在OCaml中有一个实现模块类型的模块,类型是实例的类型,值是类型类中值的实现.

然后,每次有一个"使用"Haskell中受该类型类约束的类型的函数时,您需要将该函数包装在OCaml中的模块中.这个模块(实际上是一个仿函数)将采用一个参数模块,该模块对应于我们正在使用的类型类的实例.

每次使用该函数时,您都需要首先使用该仿函数创建一个适当的模块,并将其传递给类型类的正确实例.

您会注意到Haskell和OCaml这样做的一个很大的不同之处在于,在Haskell中,当您使用最后一个函数时,编译器会为您推断出类型类的正确实例; 而使用OCaml方式,用户必须明确指定要使用的实例.


Gab*_*iba 9

尽管不像Haskell那样接近模块,但是对象类层次结构上的类类型没有清楚地解释.

请参阅类类型定义.

更新:工作示例:

type comparison = Lesser | Equal | Greater

class type comparable = object ('a)
  method compareTo: 'a -> comparison
end ;;

class type textualizable = object
  method toString: string
end ;;

(* this corresponds in Haskell to a multiparameter type class *)
class type ['b] printable = object ('a)
  constraint 'b = #textualizable         
  method printWithPrefix: 'b -> unit
end ;;

class type ['b] comparableAndPrintable = object ('a)
  inherit comparable
  inherit ['b] printable
end ;;

(* -------------- *)

class textile (str_init:string): textualizable = object
   val str = str_init
   method toString = str
end ;;

class comparableAndPrintableImpl1 (x_init: int) = object (this:'a)

  constraint 'a = 'b #comparableAndPrintable    (* interface implementation requirement *)
  constraint 'b = textualizable (* concrete type parameter *)

  val x = x_init
  method getx = x
  method compareTo (that:'a) = let r = this#getx - that#getx in
                               match r with
                               | 0 -> Equal
                               | _ when r < 0 -> Lesser
                               | _ -> Greater

  method printWithPrefix (pref: 'b)  = Printf.printf "%s %d\n" pref#toString x
end ;;

let boxSort (pivot: #comparable) (lows, equals, highs) (x: #comparable) =
      match x#compareTo pivot with
                    | Lesser -> x :: lows, equals, highs
                    | Equal -> lows, x :: equals, highs
                    | Greater -> lows, equals, x :: highs
      ;;

let rec qsort (li : #comparable list) =
      match li with
          [] | [_] -> li
          | [a;b] -> (match a#compareTo b with
                     Lesser | Equal -> [a;b]
                     | Greater -> [b;a]
                     )
          | x :: xs -> let (lows, equals, highs) = List.fold_left (boxSort x) ([], [], []) xs in
                       qsort lows @ (x :: equals) @ qsort highs
  ;;


let print_myList (prefix: 'a) (li: 'a #printable list) =
    let print_it it = it#printWithPrefix prefix in
    print_endline "\nlist: " ;
    List.iter print_it li
    ;;

let intlist (lfrom: int) (lto: int) =
   let open BatLazyList in
   to_list (range lfrom lto)              (* lazy range generator from BatLazyList *)
   ;;

let myComparableAndPrintableList =
  List.map (new comparableAndPrintableImpl1) (List.rev (intlist 1 5))
  ;;

let myprefix = new textile "x ="

let sortAndPrint (li: 'a #comparableAndPrintable list) =
   let sorted = qsort li in
   print_myList myprefix li ;
   print_myList myprefix sorted
   ;;

sortAndPrint myComparableAndPrintableList ;;
Run Code Online (Sandbox Code Playgroud)

编译和链接:

ocamlfind ocamlc -package batteries -linkpkg test.ml -o test
Run Code Online (Sandbox Code Playgroud)

  • Matias Giovanni 详细展示了如何执行此操作:http://alaska-kamtchatka.blogspot.ca/2009/08/fun-with-type-class.html (2认同)