【问题标题】:Scala case class: generating Instances for type constructor cases?Scala案例类:为类型构造函数案例生成实例?
【发布时间】:2015-02-06 16:48:03
【问题描述】:

我想使用一个通用函数来返回给定类型的“默认值”。我在以下案例类构造的帮助下实现了这一点:

case class DefaultOp[T](op: () => T)
implicit val defaultString = DefaultOp[String](() => "")
implicit val defaultInt = DefaultOp[Int](() => 0)
implicit val defaultFloat = DefaultOp[Float](() => 0.0f)
implicit val defaultDouble = DefaultOp[Double](() => 0.0d)
// ...

def default[T]()(implicit ev: DefaultOp[T]): T = ev.op()

这很好用,但我想将其扩展为也适用于从类型构造函数构造的类型。例如,我希望将任何选项类型的默认值设为“None”,并将任何列表类型设为 Nil。我该如何实施?我的第一次尝试:

implicit val defaultOption = DefaultOp[Option[_]](() => None)

编译,但是当我在应用程序中使用它时它不编译:

error: could not find implicit value for parameter ev: DefaultOp[Option[Float]]
var test: Option[Float] = default[Option[Float]]
                                  ^
one error found

有什么建议可以让它发挥作用吗?

谢谢!

【问题讨论】:

    标签: scala case-class type-constructor


    【解决方案1】:

    问题在于Option[Float] 不是Option[_],因为我们不知道_ 应该是什么。

    您可以通过将 defaultOption 设为 def 并使用类型参数来解决此问题:

    implicit def defaultOption[A] = DefaultOp[Option[A]](() => None)
    
    scala> default[Option[Float]]
    res3: Option[Float] = None
    

    【讨论】:

    • 谢谢!而已。我不知道我可以使用函数定义而不是 val ... 这导致下一个问题:隐式 def defaultDouble = DefaultOp[Double](() => 0.0d) 之间的主要区别是什么和隐式 val defaultDouble = DefaultOp[Double](() => 0.0d)?哪一个更可取,为什么?
    • 唯一的区别是一个是def,一个是val。对于defaultDouble,使用 val 很好,因为它永远不会改变。但是,对于泛型类型。 def 是必需的,因为您需要能够为(可能)任何类型生成隐式。
    • 还要注意def 将为每次调用创建一个DefaultOp 的新实例。如果这是在您的关键路径上,您可能不希望这样做。然后你可以用这个代码作弊:private val reusableDefaultOption = DefaultOp[Option[Nothing]](() => None); implicit def defaultOption[A] = reusableDefaultOption.asInstanceOf[DefaultOp[Option[A]]].
    猜你喜欢
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-10
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    相关资源
    最近更新 更多