代码之家  ›  专栏  ›  技术社区  ›  Del

如何声明模块实现了一个接口,以便签名中的一个类型与另一个类型相同?

  •  1
  • Del  · 技术社区  · 7 年前

    我正在OCaml中创建单子,需要编写它们,所以我创建了变形金刚。我用身份monad实现了transformer的常规monad:

    module type MONAD = sig
      type 'a m
      val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
      val return : 'a -> 'a m
    end
    
    module Identity : MONAD = struct
      type 'a m = 'a
      let (>>=) m f = f m
      let return x = x
    end
    
    module OptionT (M : MONAD) : MONAD with type 'a m := ('a option) M.m = struct
      type 'a m = ('a option) M.m
      let (>>=) m f = M.(>>=) m (fun option ->
        match option with
        | Some x -> f x
        | None -> M.return None)
      let return x = M.return @@ Some x
    end
    
    module Option = OptionT(Identity)
    

    但是,我不能这样做:

    open Option
    let _ = (Some 1) >>= (fun x -> Some (x + 1))
    

    错误包括:

    (Some 1)
    
    This expression has type 'a option
        but an expression was expected of type 'b option Identity.m
    
    Some (x + 1)
    
    This expression has type 'a option
        but an expression was expected of type 'b option Identity.m
    

    如果我尝试用 module Identity : MONAD with type 'a m = 'a 我在以下位置出错 module Option = OptionT(Identity) 这表明

    The type `m' is required but not provided
    

    现在看来, 'a 已替换 'a m 在签名中。

    正在执行

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

    很好用。

    我如何告诉编译器模块实现了签名,以便签名中声明的类型与另一个类型相同,同时仍保留签名的原始类型声明?

    2 回复  |  直到 7 年前
        1
  •  5
  •   octachron    7 年前

    现在看来,签名中的“a”取代了“a m”。

    这就是破坏性替换的效果

    module Identity : MONAD with type 'a m := 'a
    

    您要求编译器替换 'a m 通过 'a . 相反,标准 with 约束将类型相等添加到模块类型

     module Identity : MONAD with type 'a m = 'a
    

    看看您的各种示例,您似乎混淆了这两者,并且在打算添加类型约束时使用了破坏性替换:

    module OptionT(X:Monad) : MONAD with type 'a m = 'a = …
    (* or *) module Option : MONAD with type 'a m = 'a option = …
    

    而不是

    module OptionT(X:Monad) : MONAD with type 'a m := 'a = …
    (* nor *) module Option : MONAD with type 'a m := 'a option = …
    
        2
  •  0
  •   Étienne Millon    7 年前

    此表达式的选项类型为“a”,但表达式的选项标识类型应为“b”。m级

    事实上,编译器对 Identity 但其签名为 MONAD . ( : MONAD )不仅仅是帮助编译器,它还隐藏了有关 身份 但其签名为 单子 .

    因此,可以为其添加类型相等

    module Identity : MONAD with type 'a m = 'a = ...
    

    这是可行的。

    推荐文章