Haskell 如何将类型级别列表转换为成对链

Haskell 如何将类型级别列表转换为成对链,haskell,functional-programming,singleton-type,Haskell,Functional Programming,Singleton Type,如果没有强大的背景,单例库似乎很难处理它。有没有办法将像'[1,2,3]这样的级别类型列表转换成像'(1'(2'(3'()))这样的成对链 我试着写了几行,但它们给我带来了毫无表情的错误 {-#语言类型族,类型类型#-} 模块列表在哪里 导入数据.singleton.Prelude.List 导入数据.singleton.Prelude.Tuple 输入family-IntoChainOfPairs(xs::[k])::(k,b),其中 IntoChainOfPairs(x':'[])='(x,

如果没有强大的背景,单例库似乎很难处理它。有没有办法将像
'[1,2,3]
这样的级别类型列表转换成像
'(1'(2'(3'()))
这样的成对链

我试着写了几行,但它们给我带来了毫无表情的错误

{-#语言类型族,类型类型#-}
模块列表在哪里
导入数据.singleton.Prelude.List
导入数据.singleton.Prelude.Tuple
输入family-IntoChainOfPairs(xs::[k])::(k,b),其中
IntoChainOfPairs(x':'[])='(x,'())
IntoChainOfPairs(x):xs)='(x,IntoChainOfPairs-xs)
sIntoChainOfPairs::对于所有a(t::[a])。唱t->唱(用音符t)
sIntoChainOfPairs=\case
斯库恩斯尼尔->麻木2麻木0
烤饼a b->STuple2 a(sIntoChainOfPairs b)

所以我陷入了根本性的误解。编译器不理解我,我不理解它。我确信我的代码在根目录下是错误的。

IntoChainOfPairs的结果类型应随输入而改变。因此,实际上有两个函数,一个是计算输入的输出类型,另一个是计算输出类型

type family ToPairsType (xs :: [a]) :: Type where
  ToPairsType '[] = ()
  ToPairsType ((_ :: a) : xs) = (a, ToPairsType xs)
type family ToPairs (xs :: [a]) :: ToPairsType xs where
  ToPairs '[] = '()
  ToPairs (x : xs) = '(x, ToPairs xs)
您定义了一个分部函数,其中
b
IntoChainOfPairs
的参数。你真的写了

type family IntoChainOfPairs (k :: Type) (b :: Type) (xs :: [k]) :: (k, b) where
  IntoChainOfPairs k () (x : '[]) = '(x, '())
  IntoChainOfPairs k (k, b') (x : xs) = '(x, IntoChainOfPairs k b' xs)
其中,在
b
上进行部分模式匹配,在
k
上进行非线性匹配。此外,非自然(部分!)列表处理也没有帮助。您可以使用
Typeable
基础结构在
Type
s上痛苦地获取值级别
case
,用于将
sIntoChainOfPairs
写入,但我不建议这样做。真的,
IntoChainOfPairs
刚刚坏了

sToPairs
是作为
ToPairs
的直接“反映”编写的:

sToPairs :: forall (a :: Type) (xs :: [a]). Sing xs -> Sing (ToPairs xs)
sToPairs SNil = STuple0
sToPairs (SCons x xs) = STuple2 x (sToPairs xs)

它不是那种随着输入而改变的类型吗?@bradrn在Haskell中,类型有类型。由于历史原因,一种类型的类型通常被称为同类。我宁愿假装“善良”这个词不存在,直到有人提起它,因为这是一个故意的举动,以消除语言中的区别。@HTNW,太棒了!这种将计算分为两步的模式在单例中随处可见,现在我开始理解为什么要使用它。谢谢