我已经定义了我自己的Vect数据类型,如下所示
data MyVect : (n : Nat) -> (t : Type) -> Type where
Nil : MyVect Z t
(::) : (x : t) -> (xs : MyVect n t) -> MyVect (S n) t
然后开始为数据类型
实现Foldable接口Foldable MyVect where
foldr = ?res2
然而,当重新加载文件时,Idris投诉
When checking argument t to type constructor Prelude.Foldable.Foldable:
Type mismatch between
Nat -> Type -> Type (Type of MyVect)
and
Type -> Type (Expected type)
Specifically:
Type mismatch between
Nat
and
TypeUnification failure
稍微挠了一下头后,我猜想我可以通过写作来遵守Idris对类型构造函数的要求
Foldable (MyVect n) where
foldr = ?res2
然后我开始思考"如果我在翻转了类型参数的情况下定义了MyVect怎么办?..."
data MyVect : (t : Type) -> (n : Nat) -> Type where
Nil : MyVect t Z
(::) : (x : t) -> (xs : MyVect t n) -> MyVect t (S n)
是否可以为此参数翻转'实现可折叠界面?版本MyVect
? (以及如何?)
答案 0 :(得分:6)
您看到的类型错误来源类型为Foldable
:
Idris> :t Foldable
Foldable : (Type -> Type) -> Type
而您的MyVect
的第一个版本有类型:
Idris> :t MyVect
MyVect : Nat -> Type -> Type
,第二个有:
Idris> :t MyVect
MyVect : Type -> Nat -> Type
您可以使用普通旧功能部分应用类型。
因此Foldable (MyVect n)
有效,因为MyVect n
的类型Type -> Type
正是Foldable
接口所需的类型。
在我们确信类型的行为与函数类似之后,您可以为MyVect
提供翻转类型的别名,并且一切都会有效:
FlippedVect : Nat -> Type -> Type
FlippedVect n t = MyVect t n
Foldable (FlippedVect n) where
您还可以使用已定义的函数来实现类似的东西:
Idris> :t flip
flip : (a -> b -> c) -> b -> a -> c
Idris> :t flip MyVect
flip MyVect : Nat -> Type -> Type
现在你可以写:
Foldable (flip MyVect n) where
您甚至可以为匿名函数定义实例。这是完整版本:
Foldable (\a => MyVect a n) where
foldr f z Nil = z
foldr {n=S k} f z (x :: xs) = x `f` foldr {t=\a => MyVect a k} f z xs
foldl = believe_me -- i'm on Idris-0.12.3, I got type errors for `foldl`
-- but you can implement it in the same way
在写完所有信息后教你如何做之后,我应该说在任何情况下你绝对不应该这样做。