我一直在玩一些具有依赖类型的cofree isomporphisms,并且收到的错误消息对我来说似乎是无稽之谈。
我依赖类型的cofree
data Cofree (n :: Nat) f a where
(:<<) :: a -> f (Cofree n f a) -> Cofree ('S n) f a
和同构代码
class Iso a b where
toA :: b -> a
toB :: a -> b
和我的(非常基本的)实例(它缺少很多东西,但我想首先处理基础知识)
instance Iso (Vec ('S n) a) (Cofree ('S n) Maybe a) where
toA :: Cofree ('S n) Maybe a -> Vec ('S n) a
toA (x :<< Nothing) = VCons x VNil
我认为这是最基本的事情,但它仍然会输入错误。
错误本身:
interactive>:224:127: error:
* Could not deduce: n1 ~ 'Z
from the context: 'S n ~ 'S n1
bound by a pattern with constructor:
:<< :: forall (f :: * -> *) a (n :: Nat).
a -> f (Cofree n f a) -> Cofree ('S n) f a,
in an equation for `toA'
at <interactive>:224:112-122
`n1' is a rigid type variable bound by
a pattern with constructor:
:<< :: forall (f :: * -> *) a (n :: Nat).
a -> f (Cofree n f a) -> Cofree ('S n) f a,
in an equation for `toA'
at <interactive>:224:112
Expected type: Vec ('S n) a
Actual type: Vec ('S 'Z) a
* In the expression: VCons x VNil
In an equation for `toA': toA (x :<< Nothing) = VCons x VNil
In the instance declaration for
`Iso (Vec ('S n) a) (Cofree ('S n) Maybe a)'
这看起来很奇怪,因为我不明白为什么它不能用'Z in in n1代入类型方程,因为这似乎解决了它。
我尝试过做洞的事情(所以在我的定义中,我有:
= _ $ VCons x VNil
返回
Found hole: _ :: Vec ('S 'Z) a -> Vec ('S n) a
这看起来很奇怪,因为为什么我不能在那里提供id,它将'Z与n匹配,并且繁荣,解决了?
顺便说一下,我认为Nat和Vec的定义非常正常,所以我不想用比我需要的更多的代码来混淆这篇文章,所以如果对某些人来说更容易,我可以提供它们。
编辑: 我使用的Nat是
data Nat = Z | S Nat
我使用的Vec是
data Vec (n :: Nat) a where
VNil :: Vec 'Z a
VCons :: a -> Vec n a -> Vec ('S n) a
并且不需要导入,但GADT,DataKinds,MultiParamTypeClasses,KindSignatures和FlexibleInstances是必需的,也许PolyKinds?我不太记得。
答案 0 :(得分:1)
您无法选择n
的值。 toA
的来电者选择了这一点,toA
的定义必须与任何选择兼容。
由于无法保证呼叫者选择n ~ 'Z
,因此类型检查器会抱怨。
的确,x :<< Nothing
可以有Cofree ('S n) Maybe a
类型
但VCons x VNil
只有Vec ('S 'Z) a
类型,而不是Vec ('S n) a
。
答案 1 :(得分:1)
此处的问题是,您可以随时选择Maybe
Nothing
构造函数,但只能使用Vec
VNil
索引为Z
时的构造函数。这种不匹配使得同构无法实现。
然而,您可以通过以下方式挽救这种情况:
Cofree
的定义,以使其参数f
也被编入索引Maybe
的变体,当索引为Nothing
时,您只能使用Z
构造函数换句话说:
data ICofree (n :: Nat) f a where
(:<<) :: a -> f n (ICofree n f a) -> ICofree ('S n) f a
data IMaybe (n :: Nat) a where
INothing :: IMaybe 'Z a
IJust :: a -> IMaybe ('S n) a
instance Iso (Vec n a) (ICofree n IMaybe a) where
toA (x :<< INothing) = VCons x VNil
toA (x :<< IJust xs) = VCons x (toA xs)
toB (VCons x VNil) = x :<< INothing
toB (VCons x xs@VCons{}) = x :<< IJust (toB xs)
并a self-contained gist使用正确的导入,语言扩展和定义。