【问题标题】:Name conflict in Haskell while creating modules创建模块时 Haskell 中的名称冲突
【发布时间】:2015-07-08 17:05:15
【问题描述】:

在下面的代码中我不得不使用elem'而不是简单的elem,因为prelude已经有一个函数elem,我如何在声明Tree模块时使用elem,避免冲突??

module Tree(Tree(..), singleton, insert, elem') where

data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)

singleton :: a -> Tree a
singleton a = Node a Empty Empty

insert :: (Ord a) => a -> Tree a -> Tree a
insert e Empty = singleton e
insert e tree@(Node e2 left right)
  | e == e2 = tree
  | e > e2 = Node e2 left (insert e right)
  | e < e2 = Node e2 (insert e left) right

elem' :: (Ord a) => a -> Tree a -> Bool
e `elem'` Empty = False
e `elem'` (Node e2 left right)
  | e == e2 = True
  | e > e2 = e `elem'` right
  | e < e2 = e `elem'` left

【问题讨论】:

    标签: haskell module namespaces


    【解决方案1】:

    虽然Prelude 模块默认在作用域内,但它可以被覆盖。任何显式导入Prelude的模块在开头都有一个隐含的import Prelude;但是,如果您显式导入 Prelude,则不会添加它。因此,您可以使用hiding 导入Prelude 以外的elem

    import Prelude hiding (elem)
    

    在您的代码上下文中,这是

    module Tree(Tree(..), singleton, insert, elem) where
    
    import Prelude hiding (elem)
    
    data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
    
    -- ...
    
    elem :: (Ord a) => a -> Tree a -> Bool
    e `elem` Empty = False
    e `elem` (Node e2 left right)
      | e == e2 = True
      | e > e2 = e `elem` right
      | e < e2 = e `elem` left
    

    如果您仍然需要引用Prelude.elem,您也可以随时添加额外的import qualified Prelude 行。

    有关模块导入的更多信息,请参阅 the Haskell Wiki's nice summary of import,包括有关如何导入模块的各种选项以及一些关于(抑制)隐式 Prelude 导入的信息。


    (当然,虽然你通常不太可能需要它,但模块的最终仲裁者是the Haskell 2010 report, Ch. 5§5.3 是关于导入语法,§5.5 是关于名称冲突,§5.6 是关于Prelude(包括§5.6.2,“阴影前奏曲名”)。

    【讨论】:

    • 我觉得hiding 解决方案有点烦人的是,GHC 可能会警告您import 不是 时是无用的。但是,当您收到警告时,这意味着您应该简单地使用该文件的 NoImplicitPrelude 扩展名。仍然听起来像是 GHC 的错误行为。如果导入有一个非空的hiding 子句,并且在导入的模块和当前模块中至少定义了一个名称n,则永远不应声明它是无用的。
    • 我已经阅读了您分享的 Haskell Wiki 文章,它确实很清楚,所以只是为了完成,解决问题并仍然可以访问 Prelude 的元素 一种解决方案可能是:import Prelude hiding (elem)import qualified Prelude (elem)。这样我仍然可以访问 Prelude 的 elem,但只能通过 Prelude.elem,其他 Pelude 功能保持不变...
    猜你喜欢
    • 2011-08-21
    • 2011-07-17
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    相关资源
    最近更新 更多