OCaml-未绑定记录字段
我是OCaml新手,我正在尝试将一些Haskell代码转换为OCaml 我有下面的代码,其中我研究了OCaml模块系统和函子OCaml-未绑定记录字段,ocaml,record,functor,Ocaml,Record,Functor,我是OCaml新手,我正在尝试将一些Haskell代码转换为OCaml 我有下面的代码,其中我研究了OCaml模块系统和函子 module type F = sig type 'a f val fmap : ('a -> 'b) -> 'a f -> 'b f end module type FOO = functor (C : F) -> sig type f end module Foo : FOO =
module type F =
sig
type 'a f
val fmap : ('a -> 'b) -> 'a f -> 'b f
end
module type FOO =
functor (C : F) ->
sig
type f
end
module Foo : FOO =
functor (C : F) ->
struct
type f = { foo : 'x . 'x C.f -> 'x ;
bar : 'x . 'x C.f -> 'x C.f }
end
module List =
struct
include List
type 'a f = 'a list
let fmap = List.map
end
module Bar =
struct
include Foo (List)
let ea = { foo = List.hd ; bar = List.tl }
end
我一直有错误未绑定记录字段foo。
事实上,Foo是一个函子使事情复杂化了,我觉得我无法提供我想要的注释。
我遗漏了什么?问题的出现是因为你说Foo有Foo的签名,而在Foo中你说f是抽象的,即它的定义是隐藏的。从编译器的角度来看,您故意隐藏了Foo.f的实现细节 有几种方法可以解决此问题: 从FOO中删除签名FOO,允许对其进行推断。 模块Foo= 函子C:F-> 结构 类型f={foo:'x.'xc.f->'x; 条形图:“x.”x C.f->“x C.f} 终止 将推断其类型为 模块Foo: 函子C:F-> sig type f={foo:'x.'x C.f->'x;bar:'x.'x C.f->'x C.f;}end 在FOO中提供f的完整类型定义。 模块类型FOO= 函子C:F-> 信号 类型f={foo:'x.'xc.f->'x; 条形图:“x.”x C.f->“x C.f} 终止 在Foo和Foo中添加一个构造函数,允许您创建f类型的值,而无需知道其实现的确切细节。然而,在这种情况下,由于OCaml缺乏更高级别的多态性,这使得这变得更加困难,这意味着您无法将普遍量化的foo和bar函数直接传递给构造函数。解决方法是将这些函数包装在记录或对象中,这实际上只是将我们带回解决方案2。
问题的出现是因为你说Foo有Foo的签名,而在Foo中你说f是抽象的,也就是说它的定义是隐藏的。从编译器的角度来看,您故意隐藏了Foo.f的实现细节 有几种方法可以解决此问题: 从FOO中删除签名FOO,允许对其进行推断。 模块Foo= 函子C:F-> 结构 类型f={foo:'x.'xc.f->'x; 条形图:“x.”x C.f->“x C.f} 终止 将推断其类型为 模块Foo: 函子C:F-> sig type f={foo:'x.'x C.f->'x;bar:'x.'x C.f->'x C.f;}end 在FOO中提供f的完整类型定义。 模块类型FOO= 函子C:F-> 信号 类型f={foo:'x.'xc.f->'x; 条形图:“x.”x C.f->“x C.f} 终止 在Foo和Foo中添加一个构造函数,允许您创建f类型的值,而无需知道其实现的确切细节。然而,在这种情况下,由于OCaml缺乏更高级别的多态性,这使得这变得更加困难,这意味着您无法将普遍量化的foo和bar函数直接传递给构造函数。解决方法是将这些函数包装在记录或对象中,这实际上只是将我们带回解决方案2。
在接近OCaml的模块系统时需要注意的一点是,模块类型的主要用例之一是删除信息。此外,删除如此多的信息可能非常容易,因为受约束的模块M:S变得无用 您的模块类型FOO是删除过多信息的模块类型的一个示例。有, 模块类型FOO= 函子C:F-> 信号 f型 终止 类型f是一个抽象类型,它单独出现在生成的模块类型中。由于类型是抽象的,因此模块外的任何函数都无法创建它。而且也没有可见的方法从函子内部创建这种类型的值。因此,不可能创建这种类型的值。换句话说,该模块类型在功能上等同于 模块类型FOO=函子C:F->sig end 及 模块F:FOO=。。。 这意味着应用F只能用于其副作用
作为一般建议,当开始在OCaml中使用函子时,通常最好让编译器推断它们的类型。这避免了编写删除过多信息的模块类型这一常见问题。在接近OCaml的模块系统时需要注意的一点是,模块类型的主要用例之一是删除信息。此外,删除如此多的信息可能非常容易,因为受约束的模块M:S变得无用 您的模块类型FOO是删除过多信息的模块类型的一个示例。有, 模块类型FOO= 函子C:F-> 信号 f型 终止 类型f是一个抽象类型,它单独出现在生成的模块类型中。由于类型是抽象的,因此模块外的任何函数都无法创建它。而且也没有可见的方法从函子内部创建这种类型的值。因此,不可能创建这种类型的值。换句话说,此模块类型是功能性的 相当于 模块类型FOO=函子C:F->sig end 及 模块F:FOO=。。。 这意味着应用F只能用于其副作用 作为一般建议,当开始在OCaml中使用函子时,通常最好让编译器推断它们的类型。这样就避免了编写模块类型这一常见问题,从而删除了太多的信息