如何在Scala中将对象用作模块/仿函数?
我想使用对象实例作为模块/仿函数,或多或少,如下所示:
abstract class Lattice[E] extends Set[E] { val minimum: E val maximum: E def meet(x: E,y: E): E def join(x: E,y: E): E def neg(x: E): E } class Calculus[E](val lat: Lattice[E]) { abstract class Expr case class Var(name: String) extends Expr {...} case class Val(value: E) extends Expr {...} case class Neg(e1: Expr) extends Expr {...} case class Cnj(e1: Expr,e2: Expr) extends Expr {...} case class Dsj(e1: Expr,e2: Expr) extends Expr {...} } 这样我就可以为每个晶格创建一个不同的微积分实例(我将执行的操作需要其中的信息是晶格的最大值和最小值).我希望能够混合相同微积分的表达式,但不允许混合不同表达式的表达式.到现在为止还挺好.我可以创建我的微积分实例,但问题是我不能在其他操作它们的类中编写函数. 例如,我正在尝试创建一个解析器来读取文件中的表达式并返回它们;我也试图编写一个随机表达式生成器,用于我的ScalaCheck测试.事实证明,每次函数生成Expr对象时,我都无法在函数外部使用它.即使我创建了Calculus实例并将其作为参数传递给将依次生成Expr对象的函数,函数的返回也不会被识别为与函数外部创建的对象类型相同. 也许我的英语不够清楚,让我尝试一下我想做的玩具示例(不是真正的ScalaCheck发生器,但足够接近). def genRndExpr[E](c: Calculus[E],level: Int): Calculus[E]#Expr = { if (level > MAX_LEVEL) { val select = util.Random.nextInt(2) select match { case 0 => genRndVar(c) case 1 => genRndVal(c) } } else { val select = util.Random.nextInt(3) select match { case 0 => new c.Neg(genRndExpr(c,level+1)) case 1 => new c.Dsj(genRndExpr(c,level+1),genRndExpr(c,level+1)) case 2 => new c.Cnj(genRndExpr(c,level+1)) } } } 现在,如果我尝试编译上面的代码,我会得到很多 error: type mismatch; found : plg.mvfml.Calculus[E]#Expr required: c.Expr case 0 => new c.Neg(genRndExpr(c,level+1)) 如果我尝试做类似的事情,也会发生同样的事情: val boolCalc = new Calculus(Bool) val e1: boolCalc.Expr = genRndExpr(boolCalc) 请注意,生成器本身并不重要,但我需要在系统的其余部分做很多类似的事情(即创建和操作微积分实例表达式). 难道我做错了什么? 非常需要和赞赏这方面的帮助.非常感谢提前. 收到Apocalisp的答案并尝试后. 非常感谢您的回答,但仍有一些问题.建议的解决方案是将函数的签名更改为: def genRndExpr[E,C <: Calculus[E]](c: C,level: Int): C#Expr 我更改了所涉及的所有函数的签名:getRndExpr,getRndVal和getRndVar.我在调用这些函数时得到了相同的错误消息,并收到以下错误消息: error: inferred type arguments [Nothing,C] do not conform to method genRndVar's type parameter bounds [E,C <: plg.mvfml.Calculus[E]] case 0 => genRndVar(c) 由于编译器似乎无法找出正确的类型,我将所有函数调用更改为如下所示: case 0 => new c.Neg(genRndExpr[E,C](c,level+1)) 在此之后,在前两个函数调用(genRndVal和genRndVar)上没有编译错误,但在以下3个调用(对genRndExpr的递归调用)中,函数的返回用于构建新的Expr对象,我得到了以下错误: error: type mismatch; found : C#Expr required: c.Expr case 0 => new c.Neg(genRndExpr[E,level+1)) 所以,再一次,我被困住了.任何帮助将不胜感激. 解决方法
问题是Scala无法统一两种类型的微积分[E] #Expr和微积分[E] #Expr.
那些看起来和你一样,对吧?好吧,考虑到你可以在某些类型E上有两个不同的结石,每个类型都有自己的Expr类型.而且你不想混合两者的表达. 您需要以这样的方式约束类型:返回类型与您的Calculus参数的Expr内部类型相同的Expr类型.你要做的是: def genRndExpr[E,level: Int): C#Expr (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 从入门到进阶,全面剖析 Angular 2 新特性 | 高手问答精粹
- Angular配置Router(路由)提示Controller NaNunction/undefi
- Powershell 安装指定离线更新补丁
- angularjs – 与$location.search():如何从url当它为null时
- Bash中的数学计算总结
- 在vim中删除光标右/左部分
- Angular面试从喜剧到悲剧的十个问题
- WebService大讲堂之Axis2(7) 将Spring的装配JavaBean发布成
- 如何在bash中查看find命令的结果文件日期
- ESFramework介绍之(8)-- 客户端插件IPassiveAddin