使OCaml函数对int列表和float列表具有多态性 [英] Make OCaml function polymorphic for int lists and float lists

查看:70
本文介绍了使OCaml函数对int列表和float列表具有多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以在OCaml中创建对int和float都同样有效的多态add函数?因此,例如,如果我有类似的功能:

Is there a way to create a polymorphic add function in OCaml that works equally well for ints and floats? So for example if I have a function like:

partialsums [1; 2; 3; 4; 5]我应该得到[1; 3; 6; 10; 15],但是此功能在[1.; 2.; 3.; 4.; 5.]上不起作用,因为在OCaml中,整数和浮点数绝对不能混合.但是,如果我希望我的函数在int列表和float列表中同样能正常工作,该怎么办?是否有一个通用类型,其中int和float是子类型?如果是这样,那是什么?我对此有些迷茫.谢谢您的帮助?

partialsums [1; 2; 3; 4; 5] I should get [1; 3; 6; 10; 15] but this function won't work on [1.; 2.; 3.; 4.; 5.] because in OCaml ints and floats absolutely cannot be mixed. But what if I want my function to work equally well for int lists and float lists? Is there a general type of which int and float are sub-types? If so, what is it? I'm a little lost on this one. Thanks for the help?

推荐答案

具有参数多态性,没有.使用即席多态性,是的.

对于某些 t 类型,定义一个模块,

With parametric polymorphism, no. With ad-hoc polymorphism, yes.

For some type t, define a module,

module type Semigroup = sig
  type t
  val add : t -> t -> t
end

以及一些像partialsums这样的实用程序函数,它们在函子内部依赖于此,

and some utility functions like partialsums that rely on this inside a functor,

module Utils (S : Semigroup) = struct
  let partialsums xs =
      match xs with
      | [] -> []
      | (x::xs) ->
          List.rev (snd (List.fold_left
            (fun (acc, ys) x -> let y = S.add acc x in (y, y::ys)) (x, [x]) xs))
end

您可以获取专门针对特定类型 t

you can get the partialsums specialized to particular types t,

module IntUtils = Utils(struct type t = int
                               let add = (+) end)
module FloatUtils = Utils(struct type t = float
                                 let add = (+.) end)

let int_test = IntUtils.partialsums [1; 2; 3; 4] ;;
let float_test = FloatUtils.partialsums [1.0; 2.0; 3.0; 4.0]

这很酷,但也有些乏味;您仍然必须为函数添加特定于类型的前缀,但是至少您只需编写一次函数即可.这只是很棒的模块系统.

which is kind of cool, but also a little tedious; you still have to prefix your functions with something type-specific, but at least you only have to write the functions once. This is just the module system being awesome.

使用White,Bour和Yallop的模块化隐含性(2014),您可以写

With Modular Implicits (2014) by White, Bour and Yallop, you can write,

implicit module Semigroup_int =
  type t = int
  let add = (+)
end

implicit module Semigroup_float =
  type t = float
  let add = (+.)
end

implicit module Semigroup_string =
  type t = string
  let add = (^)
end

let add {S : Semigroup} x y = S.add x y

这将允许定义泛型重载的partialsums

which will allow the definition of a generic and overloaded partialsums,

let partialsums xs =
    match xs with
    | [] -> []
    | (x::xs) ->
        List.rev (snd (List.fold_left
          (fun (acc, ys) x -> let y = add acc x in (y, y::ys)) (x, [x]) xs))

所以现在它对于int和float都同样有效!

so now it does work equally well for ints and floats!

let int_test = partialsums [1; 2; 3; 4] ;;
let float_test = partialsums [1.0; 2.0; 3.0; 4.0]
let string_test = partialsums ["a"; "b"; "c"; "d"]

显然,已经进行了几次尝试来统一ML模块系统和Haskell的类型类概念.参见例如Dreyer的模块化类型类(2007), Harper和Chakravarty讲述了一个很好的背景故事.

There have apparently been several attempts at unifying the ML module system and Haskell's notion of type classes. See e.g. Modular Type Classes (2007) by Dreyer, Harper and Chakravarty for a good background story.

这篇关于使OCaml函数对int列表和float列表具有多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆