我有以下代码;
object main
{
def main(args: Array[String]): Unit =
{
trait E
{
def test(): Unit = println("test :)")
}
class B[T](val x: Int)
{
def inc(): B[T] with T = new B[T](x + 1) with T
}
class A[T](f : B[T] with T => Unit)
{
def apply(b: B[T] with T) = f(b)
}
val b = new B[E](0) with E
val a = new A[E](b => b.test())(b)
}
}
然而,行def inc(): B[T] with T = new B[T](x + 1) with T
没有编译,给出错误"类类型必需但T找到"并且" T需要成为混合的特征。我理解为什么会这样,但我无法找到解决问题的方法!我还没有办法约束T
成为一种特质,这让我担心这种方法不会起作用......
为了更好地说明为什么我要尝试实现这一点(只是任何人都可以提供更好的解决方案)我有一个Parsec[S, U, E, A]
类,它由接受{{State[S, U, E] with E
的函数组成。 1}}对象。我们的想法是U
是用户指定的状态,A
是解析器的结果,S
是令牌流,E
是状态的某种扩展(对于例如,人们可能希望创建Parsec[Stream[String, Char], Int, IndentationSensitive, List[Expr]]
等等。U = Int
将是用户想要计算的内容,并且不应该干扰缩进所需的状态灵敏度(两个Ints)将通过混合IndentationSensitive
特征提供。然后,如果用户想要一些其他功能,他们可以继续混合解析器的更多特征。
那么,无论如何我可以约束代码中的类型参数T
,这样我就可以将它混合成B
,或者如果没有,是否有更好的方法来完成我需要的东西?
如果我真的不清楚我想要完成什么,那么关于CodeReview的this问题说明了这种情况(在 很多 更多细节)。但Parsec[S <: Stream[_, _], U, A]
被Parsec[S <: Stream[_, _], U, E, A]
取代,而州和所有其他部分则相同。
答案 0 :(得分:0)
为了更好地说明为什么我要尝试实现这一点(只是任何人都可以提供更好的解决方案)我有一个
Parsec[S, U, E, A]
类,它由接受{{State[S, U, E] with E
的函数组成。 1}}对象。这个想法是U是用户给定的状态,A是解析器的结果,S是令牌流,E是状态的某种扩展(例如,人们可能希望创建Parsec[Stream[String, Char], Int, IndentationSensitive, List[Expr]]
在这种情况下,我只需向val extension: E
添加State
字段,然后将功能更改为接受State[S, U, E]
。如果您真的想要,可以添加从State[S, U, E]
到E
的隐式转换,这样功能就可以直接访问E
个成员,但我可能不会自己做。
答案 1 :(得分:0)
我设法找到问题的解决方案,这并不理想,但它确实解决了系统的其他几个问题。也就是说,当我们创建new State[S, U, E](input, pos, state) with E
时,使用E
添加的变量会发生什么。他们迷路了,这是一个杀手。
让我们定义一个新类型type StateBuilder[S <: Stream[_, _], U, E] = (Option[State[S, U, E] with E], S, SourcePos, U) => State[S, U, E] with E
。这个函数可以构造一个我们想要的类型的新状态,给定一个可能的先前状态和一些新状态的状态&#34;正常&#34;参数。
现在我们可以将州重新定义为;
case class State[S <: Stream[_, _], U, E](stateInput: S, statePos: SourcePos, stateUser: U, build: StateBuilder[S, U, E])
现在我们只需要一些StateBuilder[S, U, E]
,它们将在状态之间传递,但我们需要在创建初始状态时将其输入。这没关系,但这意味着用户需要了解它们是什么(这有点不利)。没有扩展名的示例构建器;
trait Default
object Default
{
def build[S <: Stream[_, _], U](s: Option[State[S, U, Default] with Default], ts: S, pos: SourcePos, u: U): State[S, U, Default] with Default =
{
new State[S, U, Default](ts, pos, u, build) with Default
}
}
可能会更复杂;
trait IndentationSensitive
{
var stateLevel: Int = 0
var stateRequiredIndent: Int = 0
}
object IndentationSensitive
{
def build[S <: Stream[_, _], U](s: Option[State[S, U, IndentationSensitive] with IndentationSensitive], ts: S, pos: SourcePos, u: U): State[S, U, IndentationSensitive] with IndentationSensitive =
{
val s_ = new State[S, U, IndentationSensitive](ts, pos, u, build) with IndentationSensitive
s match
{
case Some(s) =>
s_.stateLevel = s.stateLevel
s_.stateRequiredIndent = s.stateRequiredIndent
case None =>
s_.stateLevel = 0
s_.stateRequiredIndent = 0
}
s_
}
}
为了组合扩展,用户需要手工构建构建器功能,但是任何人都无法理解如何做到这一点并不合理。能够为每种类型自动构建这些都是很好的,但这是一个不同的问题。