使用Idris接口约束函数类型

时间:2016-05-03 00:10:31

标签: dependent-type idris

我想创建一个受接口约束的类型的函数。我的目的是使用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

1 个答案:

答案 0 :(得分:1)

正如@Cactus在评论中提到的,这里的问题是Env的类型签名不正确。具体来说,由于约束是参数的值,因此它是依赖(pi)类型,并且Idris强制执行从属类型从左到右(在使用它们之前引入)。我的理解是,编译器基本上会将参数x : a视为\Pi_{(x\;:\;a)}B(x)的简写,其中B(x)是量词右侧类型签名的一部分。这意味着(a : Type)实际上绑定了一个新的a,它与a约束中使用的VerifiedMonoid a不同(隐式普遍绑定)。

幸运的是,由于Idris不是Haskell(所有类型类约束必须位于类型签名的头部),因此很容易修复:只需将类型签名更改为Env : (a : Type) -> VerifiedMonoid a => Nat -> Type,以便{{ 1}}在使用前绑定!