【问题标题】:Scala type mismatch, cannot resolve symbol A, Pattern type is incompatible with expected typeScala 类型不匹配,无法解析符号 A,模式类型与预期类型不兼容
【发布时间】:2020-01-08 14:23:08
【问题描述】:

我正在编写 Scala 函数式编程第 5 章中的 Stream 类,我知道解决方案是在线的,但它对我没有帮助。我在上一章编写 List 类时遇到了同样的问题。

我非常沮丧,实际上将解决方案复制粘贴到我的 Scala 工作表中,但仍然是同样的问题。

我想可能是因为名字的原因(已经有一个 List 和 Stream),这样命名它们似乎不是一个聪明的主意,所以我改变了它,没有帮助。

也许这与 Intellij 有关(我正在使用 IntelliJ IDEA),我正在 Scala Worksheets 上进行练习。但我找不到任何与 IDE 相关的问题。

这是我目前所拥有的:

sealed trait StreamRED[+A]
case object Empty extends StreamRED[Nothing]
case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A]

object StreamRED {
  def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
    lazy val head = hd
    lazy val tail = tl
    Cons(() => head, () => tail)
  }
  def empty[A]: StreamRED[A] = Empty

  def apply[A](as: A*): StreamRED[A] =
    if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))

  def headOption: Option[A] = this match {
    case Empty => None
    case Cons(h,t) => Some(h())
  }

  def toList: List[A] = {
    @annotation.tailrec
    def go(s: StreamRED[A], acc: List[A]): List[A] = s match {
      case Cons(h,t) => go(t(), h() :: acc)
      case _ => acc
    }
    go(this, List()).reverse
  }
}

我收到以下错误:

Option[A](在 headOption 方法中)和 List[A] 和 StreamRED[A](在 toList 中)中的 A 上的“无法解析符号 A”

“类型不匹配。必需:StreamRED[Any],找到:StreamRED.type”在 toList 中的 this 上。

“模式类型与预期类型不兼容,在 headOption 中的 Empty 上找到:Empty.type,必需:StreamRED.type”。

Scala 新手,IntelliJ 新手,静态类型语言新手,FP 新手。非常感谢任何对优秀阅读材料的解释和建议。

【问题讨论】:

    标签: scala


    【解决方案1】:

    toListheadOption这两个函数不能在StreamRED的伴生对象中定义。

    如果您直接在 trait 中定义它们,它会起作用:

    
    sealed trait StreamRED[+A] {
    
      def headOption: Option[A] = this match {
        case Empty => None
        case Cons(h,t) => Some(h())
      }
    
     def toList: List[A] = {
        @annotation.tailrec
        def go(s: StreamRED[A], acc: List[A]): List[A] = s match {
          case Cons(h,t) => go(t(), h() :: acc)
          case _ => acc
        }
        go(this, List()).reverse
      } 
    }
    
    case object Empty extends StreamRED[Nothing]
    case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A]
    
    object StreamRED {
      def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
        lazy val head = hd
        lazy val tail = tl
        Cons(() => head, () => tail)
      }
      def empty[A]: StreamRED[A] = Empty
    
      def apply[A](as: A*): StreamRED[A] =
        if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
    }
    

    警告:this 上的模式匹配 我觉得是一种不好的做法。你确切地知道this 是什么。改为实现EmptyCons中的函数。

    改为这样做:

    sealed trait StreamRED[+A] {
      def headOption: Option[A]
      def toList: List[A]
    }
    
    case object Empty extends StreamRED[Nothing] {
      def headOption: Option[Nothing] = None
      def toList: List[Nothing] = List()
    }
    
    
    case class Cons[+A](h: () => A, t: () => StreamRED[A]) extends StreamRED[A] {
      def headOption: Option[A] = Some(h())
      def toList: List[A] = h() +: t().toList
    }
    
    object StreamRED {
      def cons[A](hd: => A, tl: => StreamRED[A]): StreamRED[A] = {
        lazy val head = hd
        lazy val tail = tl
        Cons(() => head, () => tail)
      }
      def empty[A]: StreamRED[A] = Empty
    
      def apply[A](as: A*): StreamRED[A] =
        if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
    }
    

    【讨论】:

    • “一个警告:模式匹配是不好的做法”,真的,为什么?我同意重写方法可能由于动态调度而具有更高的性能,但是 AFAIK 自我模式匹配没有任何问题,我什至会说这是 ADTs 中方法的常见实现。
    • 非常感谢!有什么建议可以让我了解什么去哪里?这是我最大的问题,比如我什么时候做一个 trait,什么时候做一个类,或者一个对象,一个单例对象,或者组合它们。唯一清楚的是案例类,喜欢它!
    • 那里有许多有用的指南,但仍然非常简单:objects 是静态的,类似单例的,case classes 是具有默认构造函数和模式匹配功能的数据定义,@987654333 @s 是需要实现的接口(尽管它们可以包含实现),classes 用于其他用途。
    • @LuisMiguelMejíaSuárez 你是指代数数据类型还是抽象数据类型
    • @LuisMiguelMejíaSuárez 我明白了。那么这可能只是我个人的口味。
    猜你喜欢
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    相关资源
    最近更新 更多