【问题标题】:Path Dependent Types example doesn't work路径依赖类型示例不起作用
【发布时间】:2016-06-10 20:07:04
【问题描述】:

Scala n00b 在这里。很确定我了解 PDT,但确定并遇到了问题;这是上一个问题Scala types: Class A is not equal to the T where T is: type T = A 的示例代码,我将在此处重现:

1: class Food
2: class Fish extends Food
3: class Grass extends Food
4:
5: abstract class Animal {
  6: type SuitableFood <: Food
  7: def eat(food: SuitableFood)
8: }
9: 
10: class Cow extends Animal {
  11: type SuitableFood = Grass
  12: override def eat(food: Grass) {}
13: }
14: 
15: val bessy: Animal = new Cow  // [1]
16: 
17: bessy eat (new bessy.SuitableFood) // [2]

原贴说这个编译,我相信应该,但不会。如果我将它粘贴到 scala REPL 中,它会成功创建 bessy [1]:

scala> val bessy: Animal = new Cow
bessy: Animal = Cow@165b8a71

但是 [2] 给了我一个我不明白的错误:

scala> bessy.eat(bessy.SuitableFood)
<console>:17: error: value SuitableFood is not a member of Animal
       bessy.eat(bessy.SuitableFood)
                       ^

如果我将它粘贴到一个文件中并“scalac”它,我会得到相同的结果。为什么? bessy 是牛对象,type SuitableFood = Grass 是在其中定义的,bessy.SuitableFood 是类类型(不是吗?)。 怎么了?

【问题讨论】:

    标签: scala path-dependent-type


    【解决方案1】:
    1. 您在(new bessy.SuitableFood) 中缺少new

    2. 1234563它只是一个抽象类型,所以 new bessy.SuitableFood 不起作用(就像 new AA 是类型参数时不起作用)。例如。考虑Animal 的其他一些子类型可以声明type SuitableFood = Food,而new Food 是非法的。 我检查过,它确实在 2.10.6 中编译,但我相信这是一个已修复的错误。

    因此我认为“new bessy.SuitableFood”会返回合适的食物,因为 .SuitableFood 将是一种虚拟类型,所以当 'Cow' 时,'SuitableFood' 将是 'grass'。如果他们不这样做,我看不到 PDT 的价值。

    这里的 PDT 的要点是,如果你确实有一个 bessy.SuitableFoodbessy 可以吃它;而且她不能吃spot.SuitableFood(除非编译器可以静态地知道它是一个子类型)。但是这个例子没有给出任何产生bessy.SuitableFood 的方法,因为没有理由假设(也没有办法告诉编译器)type SuitableFood 是一个具有公共无参数构造函数的类。您可以通过向Animal 添加方法来修复它:

    abstract class Animal {
      type SuitableFood <: Food
      def eat(food: SuitableFood)
      def newSuitableFood(): SuitableFood
    }
    
    class Cow extends Animal {
      ...
      def newSuitableFood() = new Grass
    }
    

    现在bessy.eat(bessy.newSuitableFood) 将编译并工作。

    【讨论】:

    • 我不明白第 1 点,那里有一个“新”,就在我的代码副本中。你能指出哪条线有缺陷吗?我已在原始文件中添加了行号以提供帮助。关于你的第二点,“在你解决这个问题后,bessy 被定义为动物类型,而不是牛,所以编译器不知道 bessy.SuitableFood 是草”确实!因此,我认为“new bessy.SuitableFood”会返回合适的食物,因为 .SuitableFood 将是一种虚拟类型,因此当 为“Cow”时,“SuitableFood”将是“grass”。如果他们不这样做,我看不到 PDT 的价值。
    • "[2],给了我一个我不明白的错误:scala&gt; bessy.eat(bessy.SuitableFood)"。没有new 这里。
    • "因此我认为 "new bessy.SuitableFood" 会返回合适的食物,因为 .SuitableFood 将是一种虚拟类型" 但是你为什么希望这种类型有一个没有参数的构造函数?我已经编辑了答案以解释如何正确执行此操作。
    • 我显然没有得到 PDT。我会做更多的阅读。感谢您的帮助,我已投票并接受了您的回答。
    猜你喜欢
    • 2016-06-03
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 2013-06-20
    相关资源
    最近更新 更多