Types 具有参数类型的第一类模块(类型构造函数F.F将脱离其范围)
我目前正在研究模块,看看它们可以以何种方式以类似于Haskell类型类的方式使用。目前我正在尝试使用函子类型类:Types 具有参数类型的第一类模块(类型构造函数F.F将脱离其范围),types,module,ocaml,locally-abstract-type,Types,Module,Ocaml,Locally Abstract Type,我目前正在研究模块,看看它们可以以何种方式以类似于Haskell类型类的方式使用。目前我正在尝试使用函子类型类: 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)
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
将无法正确键入,编译器将生成错误,类型构造函数F.F将退出其作用域
。我知道在这种情况下为什么会出现这个错误,但我不确定如何解决它(因为类型f是参数化的)
我已经尝试使用本地抽象类型:
let outmap (type s) (module F : Functor with type 'a f = s) f av = F.fmap f av
或
或
这些都给了我各种语法错误或打字错误
有办法解决这个问题吗
在Haskell中,这只是:
outmap : Functor f => (a -> b) -> f a -> f b
ocaml中的等价物是什么(如果有)
==编辑====
我找到了一种与工作类似的方法:
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)
但这似乎增加了很多复杂性,因为有些事情可能会简单得多。我担心您无法直接表达您想要做的事情,因为这是OCaml核心语言不支持的更高级多态性(类型构造函数上的多态性)的一个例子 有关OCaml核心语言无法支持更高级多态性的解释,请参阅中的第1.1节 由于模块系统确实支持更高级的polymophism,因此通常解决此问题的方法是将
outmap
设置为函子而不是函数
或者,上面链接的文章描述了一种变通方法(在
更高版本的库中实现——可在opam上获得),它基本上在类型级别上使用失效。这是否比使用functor更方便取决于您的具体用例。使用上述论文中的思想(假设您已定义了论文中所述的app
和Newtype1
,或者使用opam中的更高版本的包),您可以将functor定义为:
module type Functor = sig
type t
val fmap : ('a -> 'b) -> ('a, t) app -> ('b, t) app
end
module Id = Newtype1(struct type 'a t = 'a end)
module IdFunc : Functor with type t = Id.t = struct
type t = Id.t
let fmap f x = x |> Id.prj |> f |> Id.inj
end
let runId (x : ('a, Id.t) app) : 'a = Id.prj x
let outmap (type a)
(module F : Functor with type t = a)
f av =
F.fmap f av
有关更多示例,您可以查看
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)
module type Functor = sig
type t
val fmap : ('a -> 'b) -> ('a, t) app -> ('b, t) app
end
module Id = Newtype1(struct type 'a t = 'a end)
module IdFunc : Functor with type t = Id.t = struct
type t = Id.t
let fmap f x = x |> Id.prj |> f |> Id.inj
end
let runId (x : ('a, Id.t) app) : 'a = Id.prj x
let outmap (type a)
(module F : Functor with type t = a)
f av =
F.fmap f av