我想创建一个受接口约束的类型的函数。我的目的是使用contrib包中的VerifiedMonoid
模块中定义的Classes.Verified
构建一个简单的monoid求解器。
Idris给了我以下错误:
Monoid-prover.idr line 29 col 5:
When checking type of MonoidProver.eval:
Can't find implementation for VerifiedMonoid a
表示eval
的类型签名:
eval : VerifiedMonoid a => Expr n -> Env a n -> a
我做的事情愚蠢还是缺少某些东西?这种约束类型(如eval&type;类型)可以像Haskell的类型一样解释?
完整的代码如下所示。
module MonoidProver
import Classes.Verified
import Data.Fin
import Data.Vect
%default total
infixl 5 :+:
data Expr : Nat -> Type where
Var : Fin n -> Expr n
Id : Expr n
(:+:) : Expr n -> Expr n -> Expr n
Env : VerifiedMonoid a => (a : Type) -> Nat -> Type
Env a n = Vect n a
eval : VerifiedMonoid a => Expr n -> Env a n -> a
eval (Var i) env = index i env
eval Id env = neutral
eval (e :+: e') env = eval e env <+> eval e' env
答案 0 :(得分:1)
正如@Cactus在评论中提到的,这里的问题是Env
的类型签名不正确。具体来说,由于约束是参数的值,因此它是依赖(pi)类型,并且Idris强制执行从属类型从左到右(在使用它们之前引入)。我的理解是,编译器基本上会将参数x : a
视为的简写,其中是量词右侧类型签名的一部分。这意味着(a : Type)
实际上绑定了一个新的a
,它与a
约束中使用的VerifiedMonoid a
不同(隐式普遍绑定)。
幸运的是,由于Idris不是Haskell(所有类型类约束必须位于类型签名的头部),因此很容易修复:只需将类型签名更改为Env : (a : Type) -> VerifiedMonoid a => Nat -> Type
,以便{{ 1}}在使用前绑定!