Haskell“import qualified”和“Not in scope:data constructor”

时间:2015-12-31 14:43:52

标签: haskell

我有这样的导入:

import qualified Bioinformatics.DNA as DNA

来自另一个看起来像这样的文件:

data DNA = A | C | G | T
    deriving (Eq, Ord, Show)

并且在模块RNA中的这个函数中:

module Bioinformatics.RNA
  ( RNA
  , fromDna
  ) where

import qualified Bioinformatics.DNA as DNA

data RNA = A | C | G | U
    deriving (Eq, Ord, Show)

fromDna :: DNA.DNA -> RNA
fromDna DNA.A = A
fromDna DNA.C = C
fromDna DNA.G = G
fromDna DNA.T = U

我收到错误:

/home/thibaud/code/bioinformatics/src/Bioinformatics/RNA.hs:46:9:
    Not in scope: data constructor ‘DNA.A’

/home/thibaud/code/bioinformatics/src/Bioinformatics/RNA.hs:47:9:
    Not in scope: data constructor ‘DNA.C’

/home/thibaud/code/bioinformatics/src/Bioinformatics/RNA.hs:48:9:
    Not in scope: data constructor ‘DNA.G’

/home/thibaud/code/bioinformatics/src/Bioinformatics/RNA.hs:49:9:
    Not in scope: data constructor ‘DNA.T’

你知道为什么吗? 感谢

2 个答案:

答案 0 :(得分:3)

使用(..)导入数据类型的所有构造函数。

import qualified Bioinformatics.DNA as DNA (DNA(..), A, C, G, T)

代码细分

编辑:让我们分解你的代码,因为它不太习惯。

import qualified Bioinformatics.DNA as DNA (DNA(..), A, C, G, T)

这已经很奇怪了。通常人们会合格或有选择地进口,而不是两者。试试吧:

import qualified Bioinfomatics.DNA as DNA

因此,请保留量化并删除明确的符号列表。

现在供使用,你有:

fromDna :: DNA.DNA -> RNA
fromDna DNA.A = A
fromDna DNA.C = C
fromDna DNA.G = G
fromDna DNA.T = U

声称该功能从DNA转换为RNA。请注意,您的questino从未提供过RNA类型或构造函数 - 您的代码中是否包含某些内容?您发布的代码中的剩余错误与RNA有关,请考虑以下内容:

import qualified Bioinformatics.RNA as RNA

fromDna :: DNA.DNA -> RNA.RNA
fromDna DNA.A = RNA.A
fromDna DNA.C = RNA.C
fromDna DNA.G = RNA.G
fromDna DNA.T = RNA.U

答案 1 :(得分:0)

假设我们需要一个Geometry.Shape模块来对形状进行操作。首先,我们将创建一个名为Geometry的文件夹。注意大写字母G。在其中,我们将放置Shape.hs文件。这是文件将包含的内容:

module Geometry.Shape
  ( Shape(Circle,Rectangle)
  , Point
  ) where

data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)

请注意,在定义点时,我们为数据类型和值构造函数使用了相同的名称。

因此,假设我们需要Geometry模块来进行各种几何计算。我们将创建Geometry.hs文件,并将其放置在Geometry目录的同一级别:

module Geometry (area) where

import qualified Geometry.Shape as Shape

area :: Shape.Shape -> Float
area (Shape.Circle _ r) = pi * r ^ 2
area (Shape.Rectangle (Shape.Point x1 y1) (Shape.Point x2 y2)) =
    (abs $ x2 - x1) * (abs $ y2 - y1)

文件结构现在应如下所示:

.
├── Geometry
│   └── Shape.hs
└── Geometry.hs

好吧,让我们检查一下area函数。首先,我们需要在Geometry.hs文件所在的目录中打开GHCi。

$ ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude>

然后加载Geometry模块:

Prelude> :l Geometry.hs
[1 of 2] Compiling Geometry.Shape   ( Geometry/Shape.hs, interpreted )
[2 of 2] Compiling Geometry         ( Geometry.hs, interpreted )

Geometry.hs:7:24: Not in scope: data constructor ‘Shape.Point’

Geometry.hs:7:44: Not in scope: data constructor ‘Shape.Point’
Failed, modules loaded: Geometry.Shape.

糟糕!有些不对劲。可是等等!再次查看错误消息:

  

不在范围内:数据构造器“ Shape.Point”

好吧,简单地说,这意味着类型构造函数不在可访问范围内。因此,我们通过如下更改Shape.hs文件来对其进行修复:

module Geometry.Shape
  ( Shape(Circle,Rectangle)
  , Point(..)
  ) where

注意,我们将Point更改为Point(..)。重新加载模块,如下所示:

Prelude> :r
[1 of 2] Compiling Geometry.Shape   ( Geometry/Shape.hs, interpreted )
[2 of 2] Compiling Geometry         ( Geometry.hs, interpreted )
Ok, modules loaded: Geometry, Geometry.Shape.

并对其进行测试:

Prelude> area (Shape.Circle (Shape.Point 0 0) 24)
1809.5574

是的,它有效!我想提请您注意我们使用(..)来导入Point数据类型的所有构造函数这一事实。这与编写Point (Point)相同。同样,我们可以使用Shape(..)代替Shape(Circle,Rectangle)。有关更多信息,请参见:https://www.haskell.org/tutorial/modules.html

不导出数据类型的值构造函数会使它们更加抽象,从而隐藏了其实现。同样,无论使用我们模块的人,都无法与值构造函数进行模式匹配。这就是为什么以前我们在Geometry模块中遇到编译错误的原因。

我希望这个例子可以帮助您理解此类错误的原因。