1

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

    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) 
   }

    }
4

2 回答 2

3

您对 有一个隐含的定义PersonFactory[Person.Type],但是您的xform调用正在寻找而不是找到的是PersonFactory[R]。它不是同一类型。

于 2015-12-09T14:44:33.480 回答
0

我做了一些研究,并且能够想出一个实现我的想法的想法,这目前是相当令人满意的(至少对我来说)。简而言之,我想维护一个递归树结构的字符串表示,用户可以就地修改它,然后能够将该表示转换为实际实例。原来类型类是我正在寻找的。我想我会继续为那些至少和我一样不熟悉使用类型类的人发布这个。如果有人知道如何消除必须为调用“构建”提供类型参数的必要性,请告诉我。另外,我希望有一个更简洁的隐式构建器函数实现,它不使用“@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])

  }

}
于 2015-12-15T10:56:01.453 回答