如何避免Scala中类型绑定的重复 [英] How to avoid duplication of type bound in Scala

查看:90
本文介绍了如何避免Scala中类型绑定的重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有受约束的类型参数的类.

I have a class with a constrained type parameter.

我尝试使用identity,但是返回类型不精确.

I've tried with identity but the return type is not precise.

在方法identityTP中,我需要再次指定约束条件

And in the method identityTP, I need to specify again the constraint

如何避免使用适用于此类型的方法来重复此约束?

How to avoid to duplicate this constraint with methods that work on this type ?

这里是一个例子:

  sealed trait Location
  case object Single extends Location
  case object Multi extends Location

  final case class Log[L <: Location](l: L)

  def identity(log: Log[_]): Log[_] = log
  def identityTP[L<: Location](log: Log[L]): Log[L] = log

推荐答案

实际上这不是重复项. L in

Actually this is not a duplication. L in

final case class Log[L <: Location](l: L)

L in

def identityTP[L <: Location](log: Log[L]): Log[L] = log

是两个完全不同的类型参数.如果您使用其他标识符,可能会更清楚

are two completely different type parameters. This could be more clear if you used different identifiers

final case class Log[L <: Location](l: L)
def identityTP[L1 <: Location](log: Log[L1]): Log[L1] = log

一个类型参数的上限不会与其他类型参数的上限重复.

An upper bound for one type parameter doesn't duplicate an upper bound for other type parameter.

这也不是重复的,因为实际上上限可以不同

Also this is not a duplication because actually upper bounds can be different

sealed trait SubLocation extends Location
final case class Log[L <: Location](l: L)
def identityTP[L1 <: SubLocation](log: Log[L1]): Log[L1] = log

如果不想创建第二个类型参数,可以将identityTP嵌套到Log中(使其成为Log的方法)

If you don't want to create the second type parameter you can make identityTP nested into Log (making it Log's method)

final case class Log[L <: Location](l: L) {
  def identityTP: Log[L] = this
}

如果您将L设置为类型成员而不是类型参数,有时会有所帮助

Sometimes it can help if you make L a type member rather than type parameter

trait Log {
  type L <: Location
  val l: L
}
object Log {
//  def apply[_L <: Location](_l: _L): Log { type L = _L} = new Log {
//    override type L = _L
//    override val l: L = _l
//  }

  def apply[_L <: Location](_l: _L): Log = new Log {
    override type L = _L
    override val l: L = _l
  }
}

//  def identityTP(log: Log): Log = log
def identityTP(log: Log): Log { type L = log.L } = log

请注意,尽管我们必须在apply中重复上界,但在identityTP中没有.

Notice that although we have to repeat upper bound in apply but we don't have in identityTP.

通常在必要时重复上限不是什么大事

Normally it's not a big deal to repeat upper bound when necessary

class MyClass[A <: A1]
def foo[A <: A1](mc: MyClass[A]) = ???
def bar[A <: A1](mc: MyClass[A]) = ???

麻烦的时候

class MyClass[A <: A1, B <: B1, C <: C1]
def foo[A <: A1, B <: B1, C <: C1](mc: MyClass[A, B, C]) = ???
def bar[A <: A1, B <: B1, C <: C1](mc: MyClass[A, B, C]) = ???

您应该重新设计抽象.例如

you should redesign your abstractions. For example

trait Tuple {
  type A <: A1
  type B <: B1
  type C <: C1
}
class MyClass[T <: Tuple]
def foo[T <: Tuple](mc: MyClass[T]) = {
  //T#A, T#B, T#C instead of A, B, C
  ???
}

class MyClass[T <: Tuple](val t: T)
//class MyClass(val t: Tuple)

def foo[T <: Tuple](mc: MyClass[T]) = {
//def foo(mc: MyClass) = {
  import mc.t
  //t.A, t.B, t.C instead of A, B, C
  ???
}

有时您还可以使用类型约束替换类型边界

Also sometimes you can play with replacing type bounds with type constraints

final case class Log[L](l: L)(implicit ev: L <:< Location)
def identityTP[L](log: Log[L])(implicit ev: L <:< Location): Log[L] = log

尽管这不会删除重复项,但是也有一些方法可以与隐式参数(类型类)之间的重复项作斗争.参见如何包装具有隐式使用Scala中的另一种方法?

Although this doesn't remove repetitions but there are ways to fight against repetitions among implicit parameters as well (type classes). See How to wrap a method having implicits with another method in Scala?

这篇关于如何避免Scala中类型绑定的重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆