【问题标题】:Can we use the singleton .type as a type parameter?我们可以使用单例 .type 作为类型参数吗?
【发布时间】:2012-04-29 07:44:03
【问题描述】:

我正在拼凑这个问题的答案:Scala mixin to class instance,在那里我展示了一种将另一个特征或类实例“混合”到现有实例的方法:

case class Person(name: String)
val dave = Person("Dave")
val joe  = Person("Joe")

trait Dog { val dogName: String }
val spot = new Dog { val dogName = "Spot" }

implicit def daveHasDog(p: dave.type) = spot

dave.dogName //"Spot"
joe.dogName  //error: value dogName is not a member of Person

所以在本地隐式定义之后,dave 可以有效地用作Person with Dog。我的问题是,如果我们想定义一个方法,只在PersonDog 的情况下采用Person 实例,我们该怎么做?

我可以定义一个方法比如

def showDog(pd: Person with Dog) = pd.name + " shows " + pd.dogName

然而这对dave 没有好处,因为尽管他具有隐含的转换能力,但他仍然只是一个Person

我尝试定义

trait Dog [T] { val dogName: String }
val spot = new Dog [dave.type] { val dogName = "Spot" }
def showDog(p: Person)(implicit dog: Dog[p.type]) = ...

但这不合法,给error: illegal dependent method type。有什么想法吗?

【问题讨论】:

    标签: scala types type-parameter


    【解决方案1】:

    如果您使用-Ydependent-method-types 编译,您的原始代码将使用showDog 的这个定义:

    scala> def showDog(p: Person)(implicit ev: p.type => Dog) = p.name + " shows " + p.dogName
    showDog: (p: Person)(implicit ev: p.type => Dog)java.lang.String
    
    scala> showDog(dave)
    res1: java.lang.String = Dave shows Spot
    

    【讨论】:

    • 要明确一点:这需要依赖类型,因为 evtypedependentvalue 上的p。 Scala 甚至为此提供了编译器选项,这让我感到非常惊讶和印象深刻。
    • @Dan 如果默认启用就更好了。
    • @ziggystar:我认为这将在 2.10 中启用。 (实际上宏和反射系统都依赖它。)
    • @Debilski 它已在最新的 2.10 里程碑中启用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 2014-07-09
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多