为什么GHC不能在Rank 2类型的类类型族中推断出类型相等?

时间:2017-12-10 19:21:56

标签: haskell type-constraints type-families higher-rank-types

作为我正在经历的一个非常精简的版本:

{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
class ValueGen v where
  type Output v
  generate :: v -> Output v

instance ValueGen Integer where
  type Output (Integer) = Integer
  generate n = n + 1

newtype IntGenerator = Gen { generator :: forall v. ValueGen v => ((Output v) ~ Integer) => v }

myGen :: IntGenerator
myGen = Gen (3 :: Integer)

GHC给出的错误是

Could not deduce: v ~ Integer
from the context: (ValueGen v, Output v ~ Integer)
  bound by a type expected by the context:
            forall v. (ValueGen v, Output v ~ Integer) => v

如果我只是尝试通过类型相等来限制v,这样可以正常工作。

GHC遇到的问题是什么?如果已经通过v ~ Integer的输入通知,它为什么要尝试推断限制3 :: Integer?限制性检查不应该是Output Integer,其解析为Integer,等于Integer,然后通过吗?

抽象

我尝试编写一个排名2类型,其中包含两个共享一些中间类型的Pipeline类实例。基本的想法是获得两个像

这样的管道
a|---|b  b|---|c

并生成一个新类型Joined,然后是Pipeline

的实例
a|------------|c
a|---|b  b|---|c

问题在于内部管道与内部forall一起使用类型相等的限制存储到类型参数Joined - 但GHC似乎无法识别何时满足限制。< / p>

1 个答案:

答案 0 :(得分:1)

您所写的定义意味着您拥有Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null! at javax.imageio.ImageIO.read(Unknown Source) at cnbi.AgendaTelefon.Java.GUI.PaginaAdd.<init>(PaginaAdd.java:388) at cnbi.AgendaTelefon.Java.GUI.PaginaPrincipala$9.actionPerformed(PaginaPrincipala.java:371) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)

  

如果您给我一个IntGenorator并想到某种类型IntGenorator,那么v那么我会基于Output v ~ Integer内的任何内容为您提供v类型的内容{1}}

     

如果对IntGenorator这样的任何类型v,您可以给我Output v ~ Integer类型的内容,那么您可以构建v类型的内容

因为类型系列不是单射的,所以IntGenorator可以有v而不是Integer,这样Output v ~ Integer(注意它们可能位于ghc尚未编译的模块中,或者是哪个避难所还没写完。因此,ghc无法证明唯一具有v的{​​{1}}类型Output v ~ Integer(或者更确切地说是一些实现Integer的类型)并因此Num(或而3 :: Integer)是3 :: Num a => a类型的有效值。

E.g。如果有人添加了forall v. (Output v ~ Integer) => v ValueGen Char的实例,该怎么办?那么Output Char = Integer肯定不属于3类型(除非有人实现Char),因此您无法将其置于Num Char

之内