具有参数类型的一流模块(类型构造函数F.f会逃避其范围) [英] First class Modules with parametric types (The type constructor F.f would escape its scope)
问题描述
我目前正在使用模块,以查看可以哪种方式将它们以类似于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屋!