下面是一个完整的代码示例(成功编译),它是我问题的一个简化和略有牵强的例子。
“NatPair”是一对“Nat”,我想通过函数“lift_binary_op_to_pair”将二进制“Num”操作点对点地提升到“NatPair”。
但是我无法实现“Num NatPair”,因为“NatPair”不是数据构造函数。
所以,我将其包装在类型“WrappedNatPair”中,并为该类型提供了一个“Num”实现,其中包括“+”和“*”的相应“提升”版本。
然后,我想推广包装器类型的概念,使用我的“Wrapper”接口。
函数“lift_natpair_bin_op_to_wrapped”可以将二元操作从“NatPair”提升到“WrappedNatPair”,并且实现代码完全基于“unwrap”和“wrap”“Wrapper”接口方法。
但是,如果我试图推广到
(平台:Ubuntu 16.04运行Idris 1.1.1-git:83b1bed。)
“NatPair”是一对“Nat”,我想通过函数“lift_binary_op_to_pair”将二进制“Num”操作点对点地提升到“NatPair”。
但是我无法实现“Num NatPair”,因为“NatPair”不是数据构造函数。
所以,我将其包装在类型“WrappedNatPair”中,并为该类型提供了一个“Num”实现,其中包括“+”和“*”的相应“提升”版本。
然后,我想推广包装器类型的概念,使用我的“Wrapper”接口。
函数“lift_natpair_bin_op_to_wrapped”可以将二元操作从“NatPair”提升到“WrappedNatPair”,并且实现代码完全基于“unwrap”和“wrap”“Wrapper”接口方法。
但是,如果我试图推广到
lift_bin_op_to_wrapped : Wrapper t => BinaryOp WrappedType -> BinaryOp t
如果类型签名不匹配,则无法编译,会出现以下错误:
`-- Wrapping.idr line 72 col 23:
When checking type of Main.lift_bin_op_to_wrapped:
Can't find implementation for Wrapper t
(错误位置为类型签名中冒号的位置。)
我认为问题在于t
没有出现在Wrapper
接口WrapperType
方法的类型签名中,所以WrapperType
不能在接口定义之外的任何地方调用。
(解决方法是编写样板lift_<wrapped>_bin_op_to_<wrapper>
方法,并使用相同的实现代码op x y = wrap $ op (unwrap x) (unwrap y)
每次写一遍,这并不是不可忍受的。但我想清楚为什么无法编写通用的lift_bin_op_to_wrapped
方法。)
完整的成功编译代码:
%default total
PairedType : (t : Type) -> Type
PairedType t = (t, t)
NatPair : Type
NatPair = PairedType Nat
data WrappedNatPair : Type where
MkWrappedNatPair : NatPair -> WrappedNatPair
equal_pair : t -> PairedType t
equal_pair x = (x, x)
BinaryOp : Type -> Type
BinaryOp t = t -> t -> t
lift_binary_op_to_pair : BinaryOp t -> BinaryOp (PairedType t)
lift_binary_op_to_pair op (x1, x2) (y1, y2) = (op x1 y1, op x2 y2)
interface Wrapper t where
WrappedType : Type
wrap : WrappedType -> t
unwrap : t -> WrappedType
Wrapper WrappedNatPair where
WrappedType = NatPair
wrap x = MkWrappedNatPair x
unwrap (MkWrappedNatPair x) = x
lift_natpair_bin_op_to_wrapped : BinaryOp NatPair -> BinaryOp WrappedNatPair
lift_natpair_bin_op_to_wrapped op x y = wrap $ op (unwrap x) (unwrap y)
Num WrappedNatPair where
(+) = lift_natpair_bin_op_to_wrapped (lift_binary_op_to_pair (+))
(*) = lift_natpair_bin_op_to_wrapped (lift_binary_op_to_pair (*))
fromInteger x = wrap $ equal_pair (fromInteger x)
WrappedNatPair_example : the WrappedNatPair 8 = (the WrappedNatPair 2) + (the WrappedNatPair 6)
WrappedNatPair_example = Refl
(平台:Ubuntu 16.04运行Idris 1.1.1-git:83b1bed。)