创建模块时 Haskell 中的名称冲突

Name conflict in Haskell while creating modules

在下面的代码中我不得不使用elem'而不是简单的elem,因为prelude已经有一个函数elem,我怎么能在声明时使用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

虽然默认情况下 Prelude 模块在范围内,但这可以被覆盖。任何 not 显式导入 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 is on import syntax, §5.5 is on name conflicts, and §5.6 is on the Prelude (including §5.6.2、"Shadowing Prelude Names")。