如何在使用DataKinds扩展时导出类型构造函数?

时间:2016-01-05 10:05:10

标签: haskell types data-kinds

使用高级类型系统的东西。我希望有一个名字和一个 产生类型的类型构造函数:

{-# LANGUAGE DataKinds #-}

data Subject = New | Existing

在这里,据我所知,我们已经命名了Subject类型和类型构造函数 NewExisting :: Subject。这些类型构造函数没有 拿参数(我计划将它们用作幻像类型),它应该是粗略的 相当于:

{-# LANGUAGE EmptyDataDecls #-}

data New
data Existing

现在我可以写下区别了:

{-# LANGUAGE DataKinds      #-}
{-# LANGUAGE GADTs          #-}
{-# LANGUAGE KindSignatures #-}

-- …

data MyConfig :: Subject -> * -> * where
  MyConfig
    { mcOneThing :: Path t File
    } :: MyConfig k t

这甚至可以编译。令人困惑的是,数据类型的声明是 与数据类型声明无法区分,因此这段代码似乎产生了 数据类型Subject以及命名类Subject(?)它会更清晰 对我来说,我们可以指定我们在哪个级别声明事物(种类,和 然后NewExisting是类型构造函数;或类型,然后New ExistingSubject类型的值构造函数。我不 通过“宣传似乎有用的一切”来做出这个设计决定。

现在,我的问题是我无法导出NewExisting 用于其他模块的类型构造函数,例如声明如下:

foo :: MyConfig New Dir -> …

同时

foo :: MyConfig Int Dir -> …

应该是错误的,不应该编译。

以下是我尝试导出它们的方法:

module MyModule
  ( New
  , Existing
  -- …
  )
where

我得到了什么:

  

不在范围类型构造函数或类“新”

中      

不在范围类型构造函数或类“现有”

GHC手册 section 7.9.3 说要区分“类型和构造函数”,可以使用单引号',所以我试过:

module MyModule
  ( 'New
  , 'Existing
  -- …
  )
where

...但现在这是一个解析错误。

如何导出NewExisting类型构造函数,以及大多数 重要的是,我目前的理解有什么不妥吗?

1 个答案:

答案 0 :(得分:4)

使用通常的语法导出构造函数:

module MyModule (Subject(..)) where

data Subject = New | Existing

目前,提升和未提升的构造函数捆绑在一起,因此我们只能将它们一起导出/导入。

此外,您不需要在DataKinds中拥有MyModule,只需要在您打算使用提升的构造函数的模块中。