当前位置:  开发笔记 > 编程语言 > 正文

从一系列较小的实例中推断出一般的类型类实例?

如何解决《从一系列较小的实例中推断出一般的类型类实例?》经验,为你挑选了1个好方法。

这个标题肯定不是很具描述性,但我不知道如何在简短的标题中描述这一点.我很感激任何建议!

我将展示我的问题的一个非常简化的版本:)

所以我有一个类型类

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 (:<)

其中a Prod f '[a,b,c]大致相当于一个(f a, f b, f c)元组.相同的Functor,不同的类型.

编写实例非常简单:

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如何以满足的方式构建它?



1> András Kovác..:

如果类没有约束,则不能使用其方法.只需添加约束:

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

由于类型被擦除,因此在没有字典的情况下,没有任何实例可以构建运行时.从逻辑上讲,所有居民都存在一种情况,但对于程序,我们需要字典 - 建设性的证据 - 才能运行.

写出约束不应该打扰我们,因为如果我们有所有情况的实例,那么当我们需要一个实例时,我们通常可以获得一个实例,而不是太频繁的例外.例外情况是我们需要具有类型系列应用程序的开放类型的实例.在这种情况下,我们必须编写从其他已知实例显式构建所需类型的实例的函数.

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有