- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
下面的完整代码示例(已成功编译)是我的问题的简化且稍微做作的示例。
NatPair
是一对 Nat
,我想使用函数 Num
将二进制 NatPair
操作逐点“提升”到 lift_binary_op_to_pair
。
但我无法实现 Num NatPair
,因为 NatPair
不是数据构造函数。
因此,我将其包装在类型 WrappedNatPair
中,并且我可以为该类型提供 Num
实现,以及相应的“提升”版本 +
和 *
。
然后我想用我的 Wrapper
接口(interface)概括包装类型的想法。
函数lift_natpair_bin_op_to_wrapped
可以从NatPair
开始进行二进制运算到 WrappedNatPair
,实现代码完全是根据 unwrap
和 wrap
Wrapper
接口(interface)方法。
但是,如果我尝试概括为
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
接口(interface) WrapperType
方法的类型签名,所以 WrapperType
不能在内部以外的任何地方调用接口(interface)定义本身。
(解决方法是每次都使用相同的实现代码 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
(平台:运行 Idris 1.1.1-git:83b1bed 的 Ubuntu 16.04。)
最佳答案
I think the problem is that t doesn't appear anywhere in the type signature for the Wrapper interface WrapperType method, so WrapperType can't be invoked anywhere other than inside the interface definition itself.
你就在这里。这就是您收到此错误的原因。您可以通过显式指定哪些类型是包装器来修复此编译错误,如下所示:
lift_bin_op_to_wrapped : Wrapper w => BinaryOp (WrappedType {t=w}) -> BinaryOp w
lift_bin_op_to_wrapped {w} op x y = ?hole
但这可能对您没有帮助,因为 Idris 无法推断出 w
和 WrappedType
之间的对应关系。我很想看到对这个事实的解释。基本上编译器(我正在使用 Idris 1.0)告诉我接下来的事情:
- + Wrap.hole [P]
`-- w : Type
x : w
y : w
constraint : Wrapper w
op : BinaryOp WrappedType
-----------------------------------
Wrap.hole : w
您的WrappedType
依赖类型接口(interface)方法以某种棘手的方式实现类型的模式匹配。我认为这可能是您遇到问题的原因。如果您熟悉 Haskell,您可能会发现 WrappedType
和 -XTypeFamilies
之间存在一些相似之处。看这个问题: Pattern matching on Type in Idris
尽管你仍然可以实现一般的包装函数。您只需要以不同的方式设计您的界面即可。我正在使用这个问题中描述的技巧:Constraining a function argument in an interface
interface Wraps (from : Type) (to : Type) | to where
wrap : from -> to
unwrap : to -> from
Wraps NatPair WrappedNatPair where
wrap = MkWrappedNatPair
unwrap (MkWrappedNatPair x) = x
lift_bin_op_to_wrapped : Wraps from to => BinaryOp from -> BinaryOp to
lift_bin_op_to_wrapped op x y = wrap $ op (unwrap x) (unwrap y)
Num WrappedNatPair where
(+) = lift_bin_op_to_wrapped (lift_binary_op_to_pair {t=Nat} (+))
(*) = lift_bin_op_to_wrapped (lift_binary_op_to_pair {t=Nat}(*))
fromInteger = wrap . equal_pair {t=Nat} . fromInteger
这可以完美编译并运行。
关于wrapper - 我可以为表示包装其他类型的类型的 Wrapper 接口(interface)编写通用函数包装函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45646004/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!