5

使用高级类型系统的东西。我想命名 kind 和几个产生这种类型的类型构造函数:

{-# LANGUAGE DataKinds #-}

data Subject = New | Existing

在这里,据我了解,我们命名了 kindSubject和 type 构造函数 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是类型构造函数;或类型,然后NewExisting是类型事物的值构造函数Subject)。我没有通过“推广所有似乎可行的东西”来做出这个设计决定。

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

foo :: MyConfig New Dir -> …

同时在哪里

foo :: MyConfig Int Dir -> …

应该是恶意的,它不应该编译。

这是我尝试导出它们的方式:

module MyModule
  ( New
  , Existing
  -- …
  )
where

我得到什么:

不在作用域类型构造函数或类'New'中</p>

不在作用域类型构造函数或类“现有”中</p>

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

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

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


如何导出NewExisting键入构造函数,最重要的是,我目前的理解有什么问题吗?

4

1 回答 1

5

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

module MyModule (Subject(..)) where

data Subject = New | Existing

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

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

于 2016-01-05T11:13:43.523 回答