93

我正在尝试使我的库的 ghci 类型显示尽可能直观,但是在使用更高级的类型功能时遇到了很多困难。

假设我在文件中有这段代码:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data Container (xs::[*]) = Container

我在 ghci 中加载它,然后输入以下命令:

ghci> :t undefined :: Container '[String,String,String,String,String]

不幸的是,ghci 给了我相当丑陋的外观:

:: Container
       ((':)
          *
          String
          ((':)
             * String ((':) * String ((':) * String ((':) * String ('[] *))))))

ghci 删除了类型级别字符串的糖。有什么办法可以阻止 ghci 这样做并只给我漂亮的版本吗?


在相关说明中,假设我创建了一个类型级Replicate函数

data Nat1 = Zero | Succ Nat1

type family Replicate (n::Nat1) x :: [*]
type instance Replicate Zero x = '[]
type instance Replicate (Succ n) x = x ': (Replicate n x)

type LotsOfStrings = Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String

现在,当我使用 ghci 询问类型时LotsOfStrings

ghci> :t undefined :: Container LotsOfStrings

ghci 很好,给了我漂亮的结果:

undefined :: Container LotsOfStrings

但如果我要Replicated 版本,

ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)

当 ghci 对类型同义词没有这样做时,它会替换类型族:

:: Container
       ((':)
          *
          [Char]
          ((':)
             * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

为什么 ghci 代替类型族,而不是类型同义词?有没有办法控制 ghci 何时进行替换?

4

3 回答 3

2

我知道的解决方法是使用 :kind。例如,

ghci> :kind (Container '[String,String,String,String,String])

给出:

(容器'[字符串,字符串,字符串,字符串,字符串])::*

尽管

ghci>:善良!(容器'[字符串,字符串,字符串,字符串,字符串])

将打印如下内容:

容器

((':)

  *
  [Char]
  ((':)
     * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

当然,正式地,你用 ghci 向 ghci 提出了一个不同的问题kind,但它确实有效。无论如何,使用undefined ::是一种解决方法,所以我认为这可能就足够了。

于 2013-08-07T23:39:04.010 回答
2

这在即将推出的 GHC 7.8 中得到修复。

如果数据类型使用 PolyKinds,GHC 7.6 会打印种类。所以你看到(':) * String ('[] *)的不仅仅是(':) String '[].

在 GHC 7.8 中,默认情况下不再显示种类,并且您的数据类型被漂亮地打印为列表,正如您所期望的那样。您可以使用新标志-fprint-explicit-kinds来查看 GHC 7.6 中的显式种类。我不知道这是什么原因,大概是明确的种类是为了帮助理解 PolyKinds。

于 2014-02-12T23:07:36.437 回答
0
import GHC.TypeLits

data Container (xs::[*]) = Container

I load it up in ghci, then I type the following command:

:t undefined :: Container '[String,String,String,String,String]
于 2013-08-01T04:57:31.563 回答