【问题标题】:How does Haskell hide data constructor?Haskell 如何隐藏数据构造函数?
【发布时间】:2013-02-22 19:30:15
【问题描述】:

我探索了 System.Random.StdGen 并在源代码中看到了这段代码。

data StdGen = StdGen Int32 Int32

似乎模块也导出了 StdGen。

module System.Random (

    RandomGen(next, split, genRange)

    , StdGen

    ...

但是,为什么我不能在我的代码中这样做,比如,

Prelude System.Random> StdGen 1 2

Not in scope: data constructor `System.Random.StdGen'**

另一方面,我可以做到这一点,

module F (Foo) where

    import GHC.Int

    data Foo = Foo GHC.Int.Int32 GHC.Int.Int32 deriving (Show)

Prelude> Foo 1 2

Foo 1 2

有人能告诉我这个数据构造函数是如何隐藏的吗?

【问题讨论】:

    标签: haskell constructor system


    【解决方案1】:

    这里有两点需要理解。导出语法以及编译值和解释值之间 GHCi 行为的差异。

    导出语法

    使用此语法从模块中导出

    module System.Random (
        -- ...
        , StdGen
        -- ...
    

    告诉 GHC 只导出数据类型,而不是构造函数(即使两者具有相同的名称)。如果要导出构造函数,可以在数据类型名称后的括号内显式列出,如下所示:

        StdGen(StdGen)
    

    或者您可以像这样导出具有所有构造函数的数据类型:

        StdGen(..)
    

    GHCi 行为

    此外,GHCi 在加载解释 模块时,始终允许您查看模块顶层可见的所有实体,即使它们被导出列表隐藏。这是为了方便开发和调试,也是你的Foo可见的原因。

    通过在 GHCi 提示符的模块名称前放置 * 来反映这种“一切”可见的模式。如果有*,则一切都是可见的,如果没有,则导出的实体是可见的。

    使用:m命令在作用域中添加或删除模块时,您可以选择是否要在*-form中添加模块。

    对于已编译模块(以及像System.Random 这样的库模块通常已编译),*-form 不可用,所以对于这些你将始终处于遵守出口清单的情况。

    请参阅the documentation,了解有关 GHCi 作用域行为的完整描述。

    【讨论】:

    • 所以它与 GHCi 有关。非常感谢!!
    • 需要说明的是,只有在*形式加载的模块,ghci才会忽略导出列表。
    • @DanielFischer * 形式的解释模块和编译模块不是吗?
    • 如果从顶级模块导入的模块被解释,它们不会以* 形式加载(至少默认情况下)。
    • @DanielFischer 好吧,如果它们是间接导入的,那么它们根本不在范围内,这又是不同的。无论如何,我试图澄清我的答案,并提供指向行为实际文档的链接。
    【解决方案2】:

    如果您look at the sources,您会看到以下内容:

    module System.Random
        (
        -- stuff...
        , StdGen
        -- even more stuff...
        )
    

    这种语法意味着只有 type 被导出,而不是它的构造函数。如果你也想导出构造函数,你会这样做:

    module System.Random
        ( StdGen(..)
        -- ...
        )
    

    【讨论】:

    • 非常感谢!! ...但我已经在我的 Foo 中尝试过这个,为什么我仍然可以看到我的数据构造函数 Foo?
    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多