Haskell 中带括号的双点是什么意思?

What do bracketed double dots mean in Haskell?

我知道 .. 可以在范围内使用,即 [1..3] == [1,2,3],而 [10..] 是一个从 10 开始的无限列表。

但是,最近我也开始在括号内看到这些双点。作为 (..){..}.

例如,导入语句可以读取 import Colog (HasLog (..))

我的第一直觉是认为这意味着 HasLog 有几个组件,我们正在显式导入所有组件。但这与没有 (..)?

的简单导入 HasLog 有何不同?

此外,(..){..} 有何不同?

(..){..} 都是 将与数据类型相关联的名称引入范围 的方法,但它们非常不同并且在不同的上下文中使用.

  • (..) 语法专门用于 import 和导出列表。它是声明 哪些构造函数 and/or 记录您想要 import/export 的数据类型的字段 的语法的一部分。例如,如果我有一个模块

    module FooM where
    data Foo = F0 | F1 | F2
    data Bar = Bar { b0 :: Int, b1 :: Char }
    

    然后编译

    import FooM ( Foo(F1,F2), Bar(b1) )
    fu = F1
    ba = b1
    

    但这不是

    import FooM ( Foo(F1,F2) )
    fu = F0
    

    因为我只导入了 F1F2 构造函数,而不是 F0。如果我写

    import FooM ( Foo(..), Bar(..) )
    fu = F0
    ba = b0
    

    它也有效,因为这会导入 所有 构造函数和记录标签。相比之下,

    import FooM ( Foo )
    fu = F0
    

    你根本不导入任何构造函数或记录字段,而只是 Foo 作为 不透明类型 ,所以这里 fu = F0 也不会'编译。 (这经常在 export 列表中被利用,如果你希望数据类型的内部结构是“私有的”并且只能使用实用函数、智能构造函数等进行操作。)

  • {..}RecordWildCards extension. In a nutshell, it turns the names of all record labels that would apply to a parameter into locally-scoped variables.
    I would advice against using this, it's one of those extensions that tried to address the shortcomings of Haskell's record system – with IMO not much success. Better to either use records in the traditional way, or auto-generate some lenses 的一部分,使用它们可以完全避免记录问题。