我可以将构造函数与类型别名一起导出吗? [英] Can I export constructors along with a type alias?

查看:129
本文介绍了我可以将构造函数与类型别名一起导出吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据类型 data Foo ab = Bar ab ,我在库中使用它。



我也有一个更常见的具体形式的别名: type Bar = Foo Int Int



是有没有办法从我的库中导出 Bar 类型,但不是 Foo 类型?



我想这样做:

 模块Quux(
Bar )
)其中

但是当我尝试这个时,我得到错误:

 导出项'Bar(Bar)'
尝试导出在此处不可见的构造函数或类方法

以下方法可行,但我宁愿不导出 Foo 类型:

 模块Quux(
Bar
,Foo(..)
)其中


解决方案

/ em>可能在Haskell 2010中,但 poss在GHC中可以使用。

在Haskell 2010中,只能将构造函数作为数据类型的一部分导出:


数据构造函数不能在导出列表中命名,除非作为从属名称< T中的Cᵢ (C 1,C 2)],因为它们不能与类型构造函数区分开来。 [Haskell 2010 Report,§5.2导出列表,#2]


在GHC version 7.8或更新版本),但是,您可以使用 PatternSynonyms 语言扩展来完成此操作:您可以使用 pattern 来限定导出列表中的构造函数。所以,举例来说,你想要的例子是:

  { - #LANGUAGE PatternSynonyms# - } 

模块Quux(Bar,pattern Bar)其中

data Foo ab = Bar ab
type Bar = Foo Int Int

导出列表中的模式Bar 指定了构造函数,而未经修饰的 Bar

另外,如果你认为没有经过修改的 Bar 是令人困惑/不明确的,您可以使用 ExplicitNamespaces 扩展(在7.6或更高版本中)来启用类型的前缀类型构造函数,类似地:

  { - #LANGUAGE显式名称空间,PatternSynonyms# - } 
$ b $模块Quux(类型栏,模式栏)其中

data Foo ab = Bar ab
类型Bar = Foo Int Int

在文档中,有关使用模式导出构造函数:


[ W]第i -XPatternSynonyms 您可以在导入或导出列表中使用关键字 pattern 加前缀数据构造函数的名称,以允许导入或导出不带其父类型构造函数的数据构造函数 [GHC 7.10用户手册第7.3.26.4节导入/导出中的显式名称空间]


您也可以在导入中使用模式关键字/导出规范来导入或导出普通数据构造函数。例如:

  import Data.Maybe(pattern Just)

会引入数据构造函数 Just 从 Maybe 类型,而不会将类型构造函数 Maybe 带入作用域。 [GHC 7.10用户手册,第7.3.9.2节模式同义词的导入和导出)


另外,对于使用<$ c

$ b

-XExplicitNamespaces 扩展名允许您在导入或导出列表中使用类型前缀类型构造函数的名称以消除... [GHC 7.10用户手册,第7.3.26.4节导入/导出中的显式名称空间 ]







也就是说,我倾向于同意 dfeuer 在这里 - 报告不允许这样做。输入不可记下的签名 - 例如 Bar :: a - > b - > Quux.Foo a b - 有点令人发狂。但是类型同义词确实有帮助;只要确保你的文件是彻底的: - )


I have a data type data Foo a b = Bar a b that I use internally in a library.

I also have an alias for one of its more common concrete forms: type Bar = Foo Int Int.

Is there a way to export the Bar type, but not the Foo type from my library?

I'd like to do:

module Quux (
    Bar(Bar)
  ) where

But when I attempt this I get the error:

The export item ‘Bar(Bar)’
attempts to export constructors or class methods that are not visible here

The below would work, except I'd rather not export the Foo type at all:

module Quux (
    Bar
  , Foo(..)
  ) where

解决方案

This isn't possible in Haskell 2010, but is possible in GHC.

In Haskell 2010, you can only export constructors as part of a data type:

Data constructors cannot be named in export lists except as subordinate names [the Cᵢ in T(C₁,C₂)], because they cannot otherwise be distinguished from type constructors. [Haskell 2010 Report, §5.2 "Export Lists", #2]

In GHC (version 7.8 or later), however, you can use the PatternSynonyms language extension to accomplish this: with that turned on, you can qualify constructors in export lists with pattern. So, for instance, your desired example would be

{-# LANGUAGE PatternSynonyms #-}

module Quux (Bar, pattern Bar) where

data Foo a b = Bar a b
type Bar = Foo Int Int

The pattern Bar in the export list specifies the constructor, and the unadorned Bar specifies the type synonym.

In addition, if you think the unadorned Bar is confusing/ambiguous, you can use the ExplicitNamespaces extension (in version 7.6 or later) to enable prefixing type constructors with type, similarly:

{-# LANGUAGE ExplicitNamespaces, PatternSynonyms #-}

module Quux (type Bar, pattern Bar) where

data Foo a b = Bar a b
type Bar = Foo Int Int

From the documentation, about exporting constructors with pattern:

[W]ith -XPatternSynonyms you can prefix the name of a data constructor in an import or export list with the keyword pattern, to allow the import or export of a data constructor without its parent type constructor [GHC 7.10 Users Manual, §7.3.26.4 "Explicit namespaces in import/export"]

and

You may also use the pattern keyword in an import/export specification to import or export an ordinary data constructor. For example:

import Data.Maybe( pattern Just )

would bring into scope the data constructor Just from the Maybe type, without also bringing the type constructor Maybe into scope. [GHC 7.10 Users Manual, §7.3.9.2 "Import and export of pattern synonyms"]

Plus, for exporting types with type:

The -XExplicitNamespaces extension allows you to prefix the name of a type constructor in an import or export list with "type" to disambiguate… [GHC 7.10 Users Manual, §7.3.26.4 "Explicit namespaces in import/export"]


That said, I am inclined to agree with dfeuer here – there's a reason the report disallows this. Type signatures that are impossible to write down – e.g., Bar :: a -> b -> Quux.Foo a b – are a bit maddening. But the type synonym does help with that; just make sure your documentation is thorough :-)

这篇关于我可以将构造函数与类型别名一起导出吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆