Chr*_*ord 5 functional-programming scala
在本教程中学习了Scala高级类型的一些示例后,我开始讨论(a)implicits和(b)编写方法的技术,这些方法通常处理被定义为高级类型的特征的子类.我已经在(b)这里得到了一个很好的答案, 这让我更接近解决下面的问题:
我想创建一个工厂来创建单件容器(集合,列表,数组),它将我传入的项目包装到工厂函数中. [即使已经有一个Scala库可以做到这一点,我也是这样做的学习练习.但是,嘿......如果有的话,请告诉我!]
最终的结果应该让我这样做:
scala> var j: Set[String] = wrapItemInContainer("foo")
j: Set[String] = Set(foo)
scala> var k: List[Int] = wrapItemInContainer(9)
k: List[Int] = List(9)
Run Code Online (Sandbox Code Playgroud)
我想出的解决方案如下所示.我必须提供一个恼人的虚拟最终参数,以便我可以帮助编译器找出我想要的容器类型.这是有效的,但我感到困惑的是,我想将结果分配给(j,k..etc.)的变量的类型签名没有给编译器足够的信息来确定哪个隐式定义的ContainerFactory需要使用.
这个笨重的解决方案有效:
trait ContainerFactory[M[_]] { def put[A](x: A): M[A] }
implicit val factory = new ContainerFactory[List] { def put[A](x: A) = List(x) } // factory for List containers
implicit val factory2 = new ContainerFactory[Set] { def put[A](x: A) = Set(x)} // factory for Set containers
def wrapItemInContainer[ M[A]: ContainerFactory, A](item: A, helper: M[A]) : M[A] = {
val c = implicitly[ContainerFactory[M]]
c.put(item)
}
var j: List[Int] = wrapItemInContainer(9, List(0))
Run Code Online (Sandbox Code Playgroud)
但我真的想要一些没有吵闹的第二个论点:
def wrapItemInContainer[ M[A]: ContainerFactory, A](item: A) : M[A] = {
val c = implicitly[ContainerFactory[M[A]]]
c.put(item)
}
var j: List[Int] = wrapItemInContainer(9) // this does not work.
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
<console>:17: error: ambiguous implicit values:
both value factory of type => ContainerFactory[List]
and value factory2 of type => ContainerFactory[Set]
match expected type ContainerFactory[M]
var j: List[Int] = wrapItemInContainer(9)
Run Code Online (Sandbox Code Playgroud)
任何想法或提示都非常感谢!
-克里斯
您需要在M中使工厂协变.请参阅https://groups.google.com/forum/#!topic/scala-language/dQEomVCH3CI和https://issues.scala-lang.org/browse/SI-7332.
这编译:
import language.higherKinds
trait Factory[+M[_], A] { def put(x: A): M[A] }
implicit def factory1[A] =
new Factory[List, A] { def put(x: A) = List(x) }
implicit def factory2[A] =
new Factory[Set, A] { def put(x: A) = Set(x) }
def wrap[M[_], A](a: A)(
implicit factory: Factory[M, A]): M[A] =
factory.put(a)
val j: Set[String] = wrap("foo")
val k: List[Int] = wrap(9)
Run Code Online (Sandbox Code Playgroud)
我冒昧缩短你的名字.我还按照你收到的关于如何一般处理Scala高级类型的建议来编写工厂来生成类型为"X"的项目的容器,以使A成为工厂本身的类型参数.