具有参数类型的一流模块(类型构造函数F.f会逃避其范围) [英] First class Modules with parametric types (The type constructor F.f would escape its scope)

查看:75
本文介绍了具有参数类型的一流模块(类型构造函数F.f会逃避其范围)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用模块,以查看可以哪种方式将它们以类似于Haskell类型类的方式使用.目前,我正在尝试使用仿函数类型类:

I am currently playing around with modules, to see in which way they can be used in similar ways to Haskell type classes. Currently I am trying to play around with the functor type class:

module type Functor =
   sig
      type 'a f
      val fmap : ('a -> 'b) -> ('a f -> 'b f)
   end


module IdFunc =
   struct
      type 'a f  = Id of 'a
      let fmap f = fun (Id a) -> Id (f a)
      let runId  (Id a) = a
   end

let outmap (module F : Functor) av = F.fmap f av

但是,在这种情况下,outmap的键入将不正确,编译器会产生错误The type constructor F.f would escape its scope.我知道为什么在这种情况下会导致此错误,但是我不确定如何解决(因为类型f已参数化).

However in this case outmap will not be typed correctly, the compiler produces the error The type constructor F.f would escape its scope. I know why this error is caused in this case, but I am not sure how to work around it (because type f is parametrized).

我已经尝试使用本地抽象类型:

I already tried to use locally abstract types:

let outmap (type s) (module F : Functor with type 'a f = s) f av = F.fmap f av

let outmap (type a) (type b) (type fa) (type fb) 
 (module F : Functor with type a f = fa type b f = fb) f av = 
 F.fmap f av

let outmap (type s) (module F : Functor with type f = s) f av = F.fmap f av

这一切都给我各种语法错误或键入错误.

which all just give me various syntax errors or typing errors.

有什么办法可以解决这个问题?

Is there any way to work around this?

在Haskell中,这将是:

In Haskell this would just be:

outmap : Functor f => (a -> b) -> f a -> f b

ocaml(如果有的话)相当于什么?

what would be the equivalent in ocaml (if any)?

====编辑====

==== EDIT ====

我找到了一种获得与工作类似的东西的方法:

I found one way to get something similar to work:

module type Functor =
   sig
      type a
      type b
      type af
      type bf
      val fmap : (a -> b) -> (af -> bf)
   end

module type FromTo =
   sig
      type a
      type b
   end

module IdFunc =
   functor (FT : FromTo) -> 
   struct
      type a = FT.a
      type b = FT.b
      type 'a f  = Id of 'a
      type af = a f
      type bf = b f
      let fmap f = fun (Id a) -> Id (f a)
      let runId  (Id a) = a
   end

let outmap (type a') (type b') (type af') (type bf') 
   (module F : Functor 
      with type a  = a'  and
           type b  = b'  and
           type af = af' and
           type bf = bf') 
   f av =  F.fmap f av

module M = IdFunc(struct type a = int type b = string end)

let oi = outmap (module M)

let test = oi (fun _ -> "Test") (M.Id 10)

但是对于某些可能应该更简单的事情来说,这似乎增加了很多复杂性.

But this looks like a lot of added complexity for something that should probably be much simpler.

推荐答案

恐怕您不能直接表达您要尝试做的事情,因为它是种类繁多的多态性(类型构造函数上的多态性)的一个示例,而并非支持OCaml的核心语言.

I'm afraid you cannot directly express what you are trying to do because it is an example of higher-kinded polymorphism (polymorphism over type constructors) which is not supported in OCaml's core language.

有关OCaml的核心语言为何不支持更高种类的多态性的解释,请参见轻巧的更高种类的1.1节多态性.

For an explanation of why OCaml's core language cannot support higher-kinded polymorphism see Section 1.1 in Lightweight higher-kinded polymorphism.

由于模块系统支持,因此解决此问题的常用方法是将outmap用作函子而不是函数.

Since the module system does support higher-kinded polymophism, the usual solution to this problem is to make outmap a functor rather than a function.

或者,上面链接的文章介绍了一种变通方法(在higher库中实现-在opam上可用),该变通方法实质上是在类型级别使用去功能化.是否比使用函子更方便取决于您的特定用例.

Alternatively, the paper linked above describes a workaround (implemented in the higher library -- available on opam) which essentially uses defunctionalisation at the type-level. Whether this is more convenient than using functors or not depends on your specific use cases.

这篇关于具有参数类型的一流模块(类型构造函数F.f会逃避其范围)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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