Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用参数化模块的OCaml_Ocaml - Fatal编程技术网

使用参数化模块的OCaml

使用参数化模块的OCaml,ocaml,Ocaml,在OCaml中,我处理的是一个模块和一个函子 我为输入模块和函子设置了签名和结构。 然后我使用上面的模块制作了一个新模块。 事实证明,我的新模块在输入模块中不包含函数 我应该能够在我的新模块中使用函数吗? 顺便说一下,函子中的函数工作得很好。 另外,如何确保它是否是有效的模块 让我们举一个真实的例子: module type MONAD = sig type 'a t val return : 'a -> 'a t val (>>=) : 'a t -> ('

在OCaml中,我处理的是一个模块和一个函子

我为输入模块和函子设置了签名和结构。 然后我使用上面的模块制作了一个新模块。 事实证明,我的新模块在输入模块中不包含函数

我应该能够在我的新模块中使用函数吗? 顺便说一下,函子中的函数工作得很好。
另外,如何确保它是否是有效的模块

让我们举一个真实的例子:

module type MONAD = sig
  type 'a t
  val return : 'a -> 'a t
  val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
end

module MonadOps (M : MONAD) = struct
  open M (* values from M visible in scope *)
  let rec mapM f = function
    | [] -> return []
    | x::xs ->
        f x >>= fun y -> 
        mapM f xs >>= fun ys ->
        return (y :: ys)
end

module Option = struct
  type 'a t = 'a option
  let return x = Some x
  let (>>=) m f = match m with
    | None -> None
    | Some x -> f x
end

module OptionOps = MonadOps(Option)

let test = OptionOps.mapM
(* val test : ('a -> 'b Option.t) -> 'a list -> 'b list Option.t = <fun> *)
let test = OptionOps.return x
(* Error: Unbound value OptionOps.return *)
然而,我不一定建议这样做。您引入了一些冗余,这在某些情况下是很方便的(例如,如果您想
只打开一个模块,并且所有内容都在范围内),但在其他情况下也会造成一些问题,例如,如果您想组合两个模块扩展函子,您必须考虑应用它们的顺序,你可能会遇到奇怪的模块系统黑客。ML模块系统内部非常复杂,我建议您保持简单的使用,以避免陷入困境

请注意,如果不将M包含在functor中,则可以让functor的用户随时选择执行此操作:如果您决定将M直接包含在functor中,则他们有更多选项。我使用这样一个函子的方式是

(* file 'option.ml' *)
type 'a option = None | Some of 'a

module Monad = struct
  ...
end

module Ops = MonadOps(Monad)

include (Monad : MONAD with type 'a t := 'a option)
include Ops

在更简单的设置中,可以使用
M.
限定符(与任何模块一样)访问functor
F
中绑定的模块
M
导出的任何值:

或者在访问
M
的值之前使用
openm

module  F (M : sig val v : int end) =
struct
    open M
    let m_v = v
end
如果要从
F
生成的模块中获取
M
的值,必须以某种方式导出该值,或者:

  • 直接通过在新模块中对
    M
    的某些值进行混叠

    module F (...) = struct
        let v = M.v
    end
    
  • 包括整个模块

    module F (...) = struct
        include M
    end
    
    包含并不总是可能的或易于使用的,因为您可能希望在
    M
    中定义与其他类型冲突的类型名称

  • module  F (M : sig val v : int end) =
    struct
        open M
        let m_v = v
    end
    
  • 使模块成为新模块的一部分

    module F (....) = struct
        module M' = M
    end
    
    module G = F(struct let v = 5 end);;
    print_int G.M.v;;
    

包括还是不包括?它取决于函子的客户端和生成的模块的客户端。您可能在一个程序上工作,该程序必须只知道生成的模块,或者只知道函子。如果模块
M
内容是操作模块
G
所必需的,并且该模块是现成交付的,那么您必须以某种方式提供
M

请显示一些源代码。通过一个小的代码示例,我们将更好地理解您的问题……非常感谢您的帮助,didierc。我希望用更多有用的信息完成我的回答,尽管我恐怕不能比@gasche做得更好。谢谢您gasche!我得到了它。
module F (....) = struct
    module M' = M
end

module G = F(struct let v = 5 end);;
print_int G.M.v;;