我正在努力使我的库的类型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
但如果我要求Replicate
d版本,
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
ghci在类型同义词中替换为类型族:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
为什么ghci要替换类型系列,而不是类型同义词?有没有办法控制ghci何时进行替换?
答案 0 :(得分:2)
我所知道的解决方法是使用:kind。例如,
ghci的> :kind(Container'[String,String,String,String,String])
给出:
(Container'[String,String,String,String,String]):: *
虽然
ghci的> :类! (Container'[String,String,String,String,String])
将打印出类似的内容:
容器
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
正式地,当然,你问ghci与kind
有不同的问题,但它有效。无论如何,使用undefined ::
是一种解决方法,所以我认为这可能就足够了。
答案 1 :(得分:2)
这在即将发布的GHC 7.8中已得到修复。
如果数据类型使用PolyKinds,GHC 7.6会打印种类。因此,您看到(':) * String ('[] *)
而非(':) String '[]
。
在GHC 7.8中,默认情况下不再显示各种类型,并且您的数据类型将按照您的预期打印为列表。您可以使用新标记-fprint-explicit-kinds
来查看GHC 7.6中的显式类型。我不知道造成这种情况的原因,可能是明确的种类是为了帮助理解PolyKinds。
答案 2 :(得分:0)
import GHC.TypeLits
data Container (xs::[*]) = Container
我在ghci中加载它,然后输入以下命令:
:t undefined :: Container '[String,String,String,String,String]