作为我正在经历的一个非常精简的版本:
{-# 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>
答案 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