从一系列较小的类推出一般的类型类实例?
这个标题确实不是很具描述性,但我不知道如何用简短的标题来描述这个。 我会很感激任何建议!
我将介绍我的问题的一个非常简化的版本:)
所以我有一个typeclass
class Known f a where
known :: f a
这应该能够在特定的索引处生成给定类型的规范构造,对于使用GADT和其他东西非常有用。 我给出了这个简化版本,以及相关的部分。
所以显然有一个Proxy
实例:
instance Known Proxy a where
known = Proxy
我们可以使用的是:
> known :: Proxy Monad
Proxy
但是这种HList类型也有一个例子:
data Prod f :: [k] -> * where
PNil :: Prod f '[]
(:<) :: f a -> Prod f as -> Prod f (a ': as)
infixr 5 (:<)
Prod f '[a,b,c]
大致等同于(fa, fb, fc)
元组。 相同的函子,不同的类型。
编写实例非常简单:
instance Known (Prod f) '[] where
known = PNil
instance (Known f a, Known (Prod f) as) => Known (Prod f) (a ': as) where
known = known :< known
哪个效果不错:(假设一个Show实例)
> known :: Prod Proxy '[1,2,3]
Proxy :< Proxy :< Proxy :< PNil
但是,我在哪里,我需要做的全部“多态”功能的情况下, as
......但GHC不喜欢它。
asProds :: forall as. Proxy as -> Prod Proxy as
asProds _ = known :: Prod Proxy as
它出现了这个错误:
No instance for (Known (Prod f) as)
arising from a use of 'known'
我的猜测是说,GHC无法显示,将有一个实例,将挑选适用于任何工作as
,或者,它不会有一个战略,构建known
该实例。
作为一个人,我知道情况是这样,但是有什么办法可以让这个工作起作用吗? 这些实例都在“范围内”并且可用......但我怎么能告诉GHC如何以满意的方式构建它?
如果对类没有限制,则不能使用它的方法。 只需添加约束:
asProds :: forall as. Known (Prod Proxy) as => Proxy as -> Prod Proxy as
asProds _ = known :: Prod Proxy as
请注意,GHC可以推断出这种类型:
asProds (_ :: Proxy as) = known :: Prod Proxy as
-- inferred constraint
由于类型被擦除,没有字典的情况下,没有什么可以构建运行时实例。 在所有的居民中都存在这样的情况,但对于我们需要字典的程序 - 建设性证明 - 来说,这在逻辑上是正确的。
写出约束不应该让我们受到太大的影响,因为如果我们有所有情况的实例,那么当我们需要一个实例时,我们通常可以得到一个,并且不常出现异常。 当我们想要一个具有类型系列应用程序的开放类型的实例时例外。 在这种情况下,我们必须编写函数,从其他已知实例中以所需类型显式构建实例。
链接地址: http://www.djcxy.com/p/43539.html上一篇: Inferring general typeclass instance from a series of smaller ones?