代码之家  ›  专栏  ›  技术社区  ›  Beta Ziliani

OCaml-与类型别名混淆(警告40)

  •  2
  • Beta Ziliani  · 技术社区  · 7 年前

    我不明白为什么OCaml不能理解这里没有混淆的余地:下面的一个不能是另一个,而是一个。

    module A = struct
      type test = Graphics.status
    end
    
    module type ASIG = sig
      type test = A.test
      val atest : test 
    end
    
    module Func (H : ASIG) = struct
      let _ = let open H in atest.key 
    end
    

    然而,它提高了

    Warning 40: key was selected from type Graphics.status.
    It is not visible in the current scope, and will not 
    be selected if the type becomes unknown.
    

    在不禁用警告的情况下,我如何告诉它“没事”?

    我知道我可以通过打开 A 但是,如果H定义自己的函数和类型与A相似,但不等于A,则会产生不必要的冲突。我也知道我可以复制定义,但这违背了类型别名的目的,并且涉及大量不必要的代码复制。也许没有解决方案,但我想知道为什么OCaml在这个问题上如此愚蠢:类型别名应该意味着构造函数和记录字段别名,不是吗?

    2 回复  |  直到 7 年前
        1
  •  5
  •   ghilesZ Peter Miehle    7 年前

    您只需打开模块 定义原始类型 当参考该字段时,本地 key 如下所示:

    module A = struct
      type test = Graphics.status
    end
    
    module type ASIG = sig
      type test = A.test
      val atest : test 
    end
    
    module Func (H : ASIG) = struct
      let _ = let open H in atest.Graphics.key 
    end
    

    或者,如果需要参考多个字段:
    let _ = let open H in Graphics.(atest.key, atest.button)

        2
  •  1
  •   Marcelo Camargo    7 年前

    这是因为模块签名 ASIG 需要查看类型的定义 test 用于实施 A 。这通常会导致类型的可见性问题,有时需要复制类型定义,其中合同满足实现而不是引用它。

    我们如何修复此警告?在里面 ASIG公司 ,而不是定义 type test = A.test ,我们需要明确执行 type test = { anint: int } 正如我们在实施过程中所做的那样,因此:

    module ASIG = sig
      type test = { anint: int }
      val atest : test
    end
    
    module A = struct
      type test = { anint: int }
    end
    
    module Func (H : ASIG) = struct
      let _ = let open H in atest.anint
    end
    

    这个 H 模块将无法查看 anint 否则,在其范围内,因为签名具有链接到实现的类型(契约)。它也是OCaml哲学的核心概念,隔离签名和实现,并根据实现避免签名。