Scala 我希望我的函数返回一个流[T],但我可以';I don’我不知道如何进行型式检验
为了更好地学习Scala,我正在做一些基本的编程练习,但我一直在试图弄清楚为什么我的代码不会进行类型检查 关键在于Scala 我希望我的函数返回一个流[T],但我可以';I don’我不知道如何进行型式检验,scala,Scala,为了更好地学习Scala,我正在做一些基本的编程练习,但我一直在试图弄清楚为什么我的代码不会进行类型检查 关键在于功能。我想要一个函数,它返回一个包含所有可能的数字排列和给定数字列表的数学运算符的流 我很困惑,因为将函数的返回类型更改为readStream[Object]type检查得很好,返回的结果似乎是方程流。但是,下面包含的版本在返回类型possibilites设置为Stream[Equation]时不进行类型检查 作为补充说明,我知道在opsMix中添加卡并不能正确地执行操作,但我想先解
功能。我想要一个函数,它返回一个包含所有可能的数字排列和给定数字列表的数学运算符的流
我很困惑,因为将函数的返回类型更改为readStream[Object]
type检查得很好,返回的结果似乎是方程流。但是,下面包含的版本在返回类型possibilites
设置为Stream[Equation]
时不进行类型检查
作为补充说明,我知道在opsMix中添加卡并不能正确地执行操作,但我想先解决这部分问题。我想我将使用flatMap
或zipAll
和flatte
来完成这一部分
还有-这不是家庭作业强>
abstract class Operation
case class Add() extends Operation
case class Subtract() extends Operation
case class Multiply() extends Operation
case class Divide() extends Operation
case class Num(val valu: Float) extends Operation
type Equation = List[Operation]
def calc(equa: Equation): Float =
equa match {
case Num(x) :: List() => x
case Num(x) :: y :: Num(z) :: xs => y match {
case Add() => calc( Num(x + z)::xs )
case Subtract() => calc( Num(x - z)::xs )
case Multiply() => calc( Num(x * z)::xs )
case Divide() => calc( Num(x / z)::xs )
}
case _ => 0
}
// from http://stackoverflow.com/questions/1070859/listing-combinations-with-repetitions-in-scala
def mycomb[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(el <- l;
sl <- mycomb(n-1, l dropWhile { _ != el } ))
yield el :: sl
}
def comb[T](n: Int, l: List[T]): List[List[T]] = mycomb(n, l.removeDuplicates)
val ops = List(Add, Subtract, Multiply, Divide)
def possibilities(cards: List[Num]) : Stream[Equation] =
{ for {
hand <- cards.permutations
opMix <- comb(cards.length-1, ops)
} yield hand ++ opMix
}.toStream
// test value:
val ppp = possibilities(List(Num(20), Num(3), Num(7), Num(100)))
抽象类操作
case类Add()扩展了该操作
case类Subtract()扩展了该操作
case类Multiply()扩展了该操作
case类Divide()扩展了该操作
案例类Num(val-valu:Float)扩展操作
类型方程=列表[操作]
def计算(方程式:方程式):浮动=
马术比赛{
案例编号(x)::列表()=>x
大小写Num(x)::y::Num(z)::xs=>y匹配{
case Add()=>calc(Num(x+z)::xs)
大小写减法()=>calc(Num(x-z)::xs)
case Multiply()=>calc(Num(x*z)::xs)
case Divide()=>calc(Num(x/z)::xs)
}
大小写=>0
}
//从http://stackoverflow.com/questions/1070859/listing-combinations-with-repetitions-in-scala
def mycomb[T](n:Int,l:List[T]):List[List[T]]=
n匹配{
案例0=>List(List())
case \=>for(el问题在于您将操作案例类声明为Add()
等,但在val ops
中,您只使用List(Add…)
。如果您尝试使用正确的类型声明ops
:
val ops: List[Operation] = List(Add, Subtract, Multiply, Divide)
您将看到错误。(这就是为什么您自己添加类型而不是依赖类型检查器通常会很有帮助-它有助于查找错误。)
我建议您更新类层次结构,以便对单例操作使用case-object
:
abstract class Operation
case object Add extends Operation
case object Subtract extends Operation
case object Multiply extends Operation
case object Divide extends Operation
case class Num(val valu: Float) extends Operation
当然,您还需要更新您的模式:
def calc(equa: Equation): Float =
equa match {
case Num(x) :: List() => x
case Num(x) :: y :: Num(z) :: xs => y match {
case Add => calc( Num(x + z)::xs )
case Subtract => calc( Num(x - z)::xs )
case Multiply => calc( Num(x * z)::xs )
case Divide => calc( Num(x / z)::xs )
}
case _ => 0
}
然后,可能性
按预期工作,没有任何更改
或者,您可以保持类的原有方式,只需将ops
更改为
val ops: List[Operation] =
List(Add(), Subtract(), Multiply(), Divide())
更新:
关于交错,您可以执行以下操作:
def interleave[T](xs: List[T], ys: List[T], padX: T, padY: T): List[T] =
xs.zipAll(ys, padX, padY).flatMap(pair => List(pair._1, pair._2))
def interleave[T](xs: List[T], ys: List[T]): List[T] = {
import collection.mutable._;
@annotation.tailrec
def f(xs: List[T], ys: List[T], r: Buffer[T]): Buffer[T] =
xs match {
// By swapping the arguments, we get interelaving:
case x :: xrest => f(ys, xrest, r += x);
case Nil => r ++= ys;
}
return f(xs, ys, new ArrayBuffer[T]).toList;
}
但请注意,结果总是有偶数个元素。也许更好的解决方案是自己实现交织
,例如:
def interleave[T](xs: List[T], ys: List[T], padX: T, padY: T): List[T] =
xs.zipAll(ys, padX, padY).flatMap(pair => List(pair._1, pair._2))
def interleave[T](xs: List[T], ys: List[T]): List[T] = {
import collection.mutable._;
@annotation.tailrec
def f(xs: List[T], ys: List[T], r: Buffer[T]): Buffer[T] =
xs match {
// By swapping the arguments, we get interelaving:
case x :: xrest => f(ys, xrest, r += x);
case Nil => r ++= ys;
}
return f(xs, ys, new ArrayBuffer[T]).toList;
}
但是,我想说更好的解决方案是不要混合运算和数字。相反,您可以为由符号形成的格式良好的表达式声明一个特殊类,例如(未测试):
而不是创建一个交错列表,而是创建一个Expression
的实例。问题是您将您的操作用例类声明为Add()
等,但在val ops
中,您只使用list(Add…)
。如果您尝试使用正确的类型声明ops
:
val ops: List[Operation] = List(Add, Subtract, Multiply, Divide)
您将看到错误。(这就是为什么您自己添加类型而不是依赖类型检查器通常会很有帮助-它有助于查找错误。)
我建议您更新类层次结构,以便对单例操作使用case-object
:
abstract class Operation
case object Add extends Operation
case object Subtract extends Operation
case object Multiply extends Operation
case object Divide extends Operation
case class Num(val valu: Float) extends Operation
当然,您还需要更新您的模式:
def calc(equa: Equation): Float =
equa match {
case Num(x) :: List() => x
case Num(x) :: y :: Num(z) :: xs => y match {
case Add => calc( Num(x + z)::xs )
case Subtract => calc( Num(x - z)::xs )
case Multiply => calc( Num(x * z)::xs )
case Divide => calc( Num(x / z)::xs )
}
case _ => 0
}
然后,可能性
按预期工作,没有任何更改
或者,您可以保持类的原有方式,只需将ops
更改为
val ops: List[Operation] =
List(Add(), Subtract(), Multiply(), Divide())
更新:
关于交错,您可以执行以下操作:
def interleave[T](xs: List[T], ys: List[T], padX: T, padY: T): List[T] =
xs.zipAll(ys, padX, padY).flatMap(pair => List(pair._1, pair._2))
def interleave[T](xs: List[T], ys: List[T]): List[T] = {
import collection.mutable._;
@annotation.tailrec
def f(xs: List[T], ys: List[T], r: Buffer[T]): Buffer[T] =
xs match {
// By swapping the arguments, we get interelaving:
case x :: xrest => f(ys, xrest, r += x);
case Nil => r ++= ys;
}
return f(xs, ys, new ArrayBuffer[T]).toList;
}
但请注意,结果总是有偶数个元素。也许更好的解决方案是自己实现交织
,例如:
def interleave[T](xs: List[T], ys: List[T], padX: T, padY: T): List[T] =
xs.zipAll(ys, padX, padY).flatMap(pair => List(pair._1, pair._2))
def interleave[T](xs: List[T], ys: List[T]): List[T] = {
import collection.mutable._;
@annotation.tailrec
def f(xs: List[T], ys: List[T], r: Buffer[T]): Buffer[T] =
xs match {
// By swapping the arguments, we get interelaving:
case x :: xrest => f(ys, xrest, r += x);
case Nil => r ++= ys;
}
return f(xs, ys, new ArrayBuffer[T]).toList;
}
但是,我想说更好的解决方案是不要混合运算和数字。相反,您可以为由符号形成的格式良好的表达式声明一个特殊类,例如(未测试):
而不是创建一个交错列表,而是创建一个表达式的实例谢谢,回答得很好。你的建议完全正确。现在,当我按照计划尝试使用zipAll和flatten时,我遇到了另一个与类型相关的错误…你的第一个想法是如何放置卡和opMix
交错排列的项目?@DustMason我在答案中添加了一些想法。非常有用,谢谢!您最后的建议更像是“scala方式”对我来说,因为它解决了定义良好的类型化类的问题。谢谢,回答很好。你的建议完全正确。现在,当我按照计划尝试使用zipAll和flatten时,我遇到了另一个与类型相关的错误…你第一个将卡
s和opMix
项按交错顺序排列的想法是什么?@DustMason我在答案中添加了一些想法。非常有用,谢谢!您最后的建议对我来说更像是“scala方式”,因为它通过定义良好的类型化类解决了问题。