在 Idris 中,Vect n a
是一个数据类型,表示一个长度为 n 的向量,其中包含类型 a 的项。想象一下我有一个功能:
foo : Int -> Vect 4 Int
foo n = [n-1, n, n+1, n*4]
函数的主体并不重要,它可以是任何返回 4 个 Ints 的向量的东西。现在,我想将此函数与 concatMap 一起使用,如下所示:
bar : Vect n Int -> Vect (4*n) Int
bar vals = concatMap foo vals
Bar 是一个函数,它接受长度为 n 的 Int 向量并返回长度为 4*n 的向量。
concatMap 的类型签名是:
Prelude.Foldable.concatMap : Foldable t => Monoid m => (a -> m) -> t a -> m
因此,如果我尝试编译 bar,我会收到错误消息:
When elaborating right hand side of bar:
Can't resolve type class Monoid (Vect (plus n (plus n (plus n (plus n 0)))) Int)
这意味着 Vect n Int 不是幺半群的实例。为了使它成为一个幺半群的实例,我需要实现:
Prelude.Algebra.neutral : Monoid a => a
不幸的是,我不确定如何做到这一点。List实现了monoid,如下:
instance Monoid (List a) where
neutral = []
但是,如果我尝试为 Vect n Int 实现带有中性 = [] 的幺半群,我会收到错误消息:
When elaborating right hand side of Prelude.Algebra.Vect n Int instance of Prelude.Algebra.Monoid, method neutral:
| Can't unify
| Vect 0 Int
| with
| Vect n Int
|
| Specifically:
| Can't unify
| 0
| with
| n
所以我想知道,我将如何为 Vect 实现幺半群?