Scala无法找到隐含的,我也不知道为什么 - 有人能指出正确的方向吗?

时间:2015-12-09 14:28:15

标签: scala scala-implicits

我正在尝试编写工厂来创建案例类。我正在创建一个命令行工具,它接受案例类参数的字符串表示。无论如何,想法是限制为新类型创建隐式的添加更改,但我似乎无法超越起始线。下面是一些试图创建一个case对象的代码(所以没有参数 - 最简单的情况),但是scalac抱怨它"找不到参数factory"的隐含值。一定是stoopid的东西,但我已经尝试了我能想到的一切。如果有人能指出我正确的方向,那将是非常感激的。感谢。

    object Message {

      case object Person


      sealed trait Repr[T] {
        def value: T
      }


      trait Parm0Factory[R] {
        def instance(): R
      }


      implicit val personFactory = new Parm0Factory[Person.type] {
        def instance() = Person
      }


      case class Parm0[R]() extends Repr[R] {
        override def value(): R = xform

        private def xform(implicit factory: Parm0Factory[R]): R = factory.instance()
      }

   def main(args: Array[String]): Unit = { 
      val t1 = Parm0[Person.type]() 
      println(t1.value) 
   }

    }

2 个答案:

答案 0 :(得分:3)

您有vector<Mat> RImages; vector<Mat> hImages; RImages.reserve(blocks_width * blocks_height); hImages.reserve(blocks_width * blocks_height); for ( int idx = 0; idx < blocks_width * blocks_height; idx++ ) { ... Mat temp; RImages.emplace_back(imread( filename , 1 ) ); cvtColor( RImages[ idx ], temp , CV_BGR2HSV ); hImages.emplace_back(temp ); } 的隐式定义,但您的PersonFactory[Person.Type]来电正在寻找而未找到的是xform。它的类型不同。

答案 1 :(得分:0)

我做了一些研究,并且能够提出我的想法的实现,现在非常令人满意(至少对我来说)。简而言之,我想维护一个用户可以就地修改的递归树结构的String表示,然后能够将该表示转换为实际的实例。结果类型类是我正在寻找的。以为我会继续发布这个,因为那里的人至少不像我那样熟悉使用类型类。 如果有人知道如何删除必须提供类型参数来调用'build',请告诉我。此外,我希望有一个更清晰的隐式构建器函数实现,它不使用'@unchecked'注释来消除烦人的编译器警告。 : - )

object Messages {

  // Test classes
  case class Person(name: String, age: Int, pet: Dog)

  case class Dog(name: String)

  case class Device(deviceType: DeviceType, on: Boolean)

  sealed trait DeviceType

  case class Android() extends DeviceType

  case class iOS() extends DeviceType

  case class Windows() extends DeviceType



  // Builders...
  trait Builder[A] {
    def build: Node => A
  }

  object Builder {
    def build[A](f: Node => A) = new Builder[A] {
      val build = f
    }

    // Terminals...
    implicit val intBuilder: Builder[Int] = build(node => (node: @unchecked) match {
      case Term(_, value) => value.toInt
    })
    implicit val stringBuilder: Builder[String] = build(node => (node: @unchecked) match {
      case Term(_, value) => value
    })
    implicit val booleanBuilder: Builder[Boolean] = build(node => (node: @unchecked) match {
      case Term(_, value) => value.toBoolean
    })


    // Case classes (composites)
    implicit val dogBuilder: Builder[Dog] = build[Dog](node => (node: @unchecked) match {
      case Tree(_, children) =>
        Dog(children(0).build[String])
    })

    implicit val personBuilder: Builder[Person] = build[Person](node => (node: @unchecked) match {
      case Tree(_, children) =>
        Person(children(0).build[String], children(1).build[Int], children(2).build[Dog])
    })

    implicit val deviceTypeBuilder: Builder[DeviceType] = build[DeviceType](node => (node: @unchecked) match {
      case Term(_, value) => value match {
        case "Android" => Android()
        case "iOS" => iOS()
        case "Windows" => Windows()
      }
    })

    implicit val deviceBuilder: Builder[Device] = build[Device] (node => (node: @unchecked) match {
      case Tree(_, children) => Device(children(0).build[DeviceType], children(1).build[Boolean])
    })
  }


  // Data Structures...
  sealed trait Node {
    val name: String

    def prompt: String

    def build[A: Builder]: A = implicitly[Builder[A]].build(this)
  }

  case class Tree(name: String, children: IndexedSeq[Node]) extends Node {
    override def prompt = {
      val choices = children.zipWithIndex.map { case (node, idx) => s"${idx + 1}) ${node.name}" }.mkString("\n")
      s"$toString\n$choices\n"
    }

    override def toString = name + children.mkString("(", ", ", ")")
  }

  case class Term(name: String, value: String) extends Node {
    override def prompt = s"$name = "

    override def toString = s"$name = $value"
  }


  def main(args: Array[String]): Unit = {

    val person = Tree("Person", IndexedSeq[Node](Term("name", "Fred"), Term("age", "45"),
      Tree("pet", IndexedSeq[Node](Term("name", "Fido")))))

    val device = Tree("some device", IndexedSeq[Node](Term("type", "iOS"), Term("on", "true")))

    println(person.prompt)
    println(person.toString)

    // TODO How to remove necessity of providing type parameter?
    println(person.build[Person])

    println(device.build[Device])

  }

}