在OCaml中Haskell的types类最接近什么?
有什么方法可以完成Haskell的类类在OCaml中的工作? 基本上,我想写一个多态的函数,而不写太多的代码。 做多态的典型方法是提供一个额外的参数,告诉函数是目前正在处理的types。 例如,假设我想对整数列表进行sorting,我必须将一个额外的比较器传递给该函数。
type comparison = Lesser | Equal | Greater my_sort : (a' -> a' -> comparison) -> 'a list -> 'a list
无论如何告诉OCaml,我的types是可比较的,而不用为每种我想要分类的types编写比较器函数? 这意味着我的sortingfunction看起来就像这样:
my_sort : 'a list -> 'a list
这真的取决于你想达到什么。
如果您对OCaml多态比较函数(这对于循环函数和函数值不起作用)感到满意,则可以简单地编写:
let my_sort l = List.sort Pervasives.compare l
模仿types类的更一般的方法是使用函子:
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 xy = y - x (* Reverse order *) end module SortAsc = MySort(IntAscending) module SortDesc = MySort(IntDescending)
这在Derek Dreyer,Robert Harper和Manuel MT Chakravarty的“ Modular Type Classes ”中有详细的解释。 在第34届年度ACM SIGPLAN – SIGACT研讨会上,编程语言原则,ACM出版社,2007年。摘要:
ML模块和Haskelltypes已被certificate是用于程序构造的高效工具。 模块强调程序组件的显式configuration和数据抽象的使用。 types类强调隐式的程序构造和ad hoc多态性。 在本文中,我们通过查看types类作为特定的模块使用模式,展示如何在明确types的模块语言框架内支持types类编程的隐式types风格。 这个视图提供了模块和types类的和谐集成,其中类类的特征(例如类层次结构和相关types)自然产生为现有模块语言结构(例如模块层次结构和types组件)的使用。 另外,程序员可以明确地控制哪些types实例可以被给定范围内的types推断使用。 我们将我们的方法forms化为哈珀 – 斯通风格的精化关系,并提供一个完善的types推断algorithm作为实现的指导。
我遇到了一篇非常好的文章,演示了Haskell中的types和types类以及OCaml中的模块和模块types之间的转换: http : //conway.rutgers.edu/~ccshan/wiki/blog/posts/Translations/
基本上,正如@Thomas所示,Haskell中的types类成为OCaml中的一个types(实现typestypes的types)和一堆使用该types的值的模块types。
然后,对应于Haskell中types类的“实例”,OCaml中有一个模块实现模块types,types是实例的types,值是types类中值的实现。
然后,每当你有一个“使用”Haskelltypes约束types的函数时,你需要将这个函数包装在OCaml模块中。 这个模块(实际上是一个仿函数)将采用一个参数模块,它对应于我们正在使用的types实例。
每次使用该函数时,都需要先使用该函数创build一个适当的模块,并将其传递给types类的正确实例。
你会注意到Haskell和OCaml的一个很大的不同之处在于,在Haskell中,当你使用最后一个函数时,编译器会为你推导出适当的types实例; 而使用OCaml的方式,用户必须明确指定要使用的实例。
尽pipe不像模块那样接近Haskell,但是在对象类的层次结构上的类types并没有被清楚地解释。
见类的定义 。
更新:工作示例:
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 ;;
编译和链接:
ocamlfind ocamlc -package batteries -linkpkg test.ml -o test
一般来说,由于OCaml不支持隐式参数,因此需要某种字典参数来显式传递types实例。 这可以通过多态logging,头等模块或对象来实现。 我有一个示例项目显示使用模块的方式: https : //github.com/hongchangwu/ocaml-type-classes