以下类型族
type family ListVariadic (as :: [Type]) (b :: Type) = (f :: Type) where
ListVariadic (a ': as) b = a -> ListVariadic as b
ListVariadic '[] b = b
显然不是单射的,例如ListVariadic '[] (a -> a) ~ ListVariadic '[a] a
。
但是,具有内射性来帮助进行类型推断非常方便,而且我不打算将ListVariadic
的第二个参数用作函数类型。
我提出了两种解决方法,但都不太令人满意:
选项1:(通过类型类)传递见证了ListVariadic左逆的类型族。
type family Arguments (f :: Type) :: [Type] where
Arguments (a -> b) = a ': Arguments b
Arguments b = '[]
type family Return (f :: Type) :: Type where
Return (a -> b) = Return b
Return b = b
class ( f ~ ListVariadic (Arguments f) (Return f) ) => VariadicIsInjective f where
instance ( f ~ ListVariadic (Arguments f) (Return f) ) => VariadicIsInjective f where
对我来说,这最终引入了太多的复杂性,不得不将这些辅助类型贯穿于整个线程中。
选项2。在可变参数类型族的定义中明确列出一个将要使用的所有非功能类型:
type family ListVariadic (as :: [Type]) (b :: Type) = (f :: Type) | f -> as b where
ListVariadic (a ': as) b = a -> ListVariadic as b
ListVariadic '[] () = ()
ListVariadic '[] Bool = Bool
ListVariadic '[] Word = Word
ListVariadic '[] Int = Int
ListVariadic '[] Float = Float
ListVariadic '[] Double = Double
... ... ...
ListVariadic '[] (a,b) = (a,b)
ListVariadic '[] (a,b,c) = (a,b,c)
... ... ...
ListVariadic '[] [a] = [a]
... ... ...
然后,一个内注性注释是可能的,并且可以按预期工作。显然,它的局限性很强……并且最终仍然以a ~ ListVariadic '[] a
形式的约束条件需要传递。
我希望有一种写ListVariadic
类型族(或实现相同目的的东西)的方法,指出它的第二个参数不是函数,并允许插入性注释。
我知道我很麻烦,因为在提供的ListVariadic
的第一个定义中,第二个等式在右侧有一个裸类型变量。通常在检查内射性时是不允许的...但是也许有一些使用类型同义词的巧妙技巧可以解决此问题?