在Scala中可以实现以下功能:
scala> val l = List
l: scala.collection.immutable.List.type = scala.collection.immutable.List$@7960c21a
scala> l ( 1, 2, 3 )
res0: List[Int] = List(1, 2, 3)换句话说,Scala具有更高阶的多态性。我想使用高阶多态性来做以下事情。
sealed abstract class A { def eval () : A }
case class A0 () extends A { ... }
case class A1 ( a : A ) extends A { ... }
case class A2 ( a : A, b : A ) extends A { ... }
....所以我有一堆case类,A的子类,它们的构造函数不一定接受相同数量的参数。我也希望有一个‘泛型’的case类,就像这样:
case class ApplyA ( c : ???, l : List [ A ] ) extends A {
def eval () : A = { ??? } }其思想是,ApplyA将A的子类型的构造函数和一组参数作为第一个参数。然后,如果可能,eval方法使用构造函数构造一个合适的类(即列表具有正确的长度)并返回它(这对应于上面List示例中的l ( 1, 2, 3) )。ApplyA的第一个构造函数的参数类型是什么
对于高阶多态性,这应该是可能的,但我不知道如何实现。我知道,即使不使用高阶多态性也可以做到这一点,只需将构造函数包装在函数中,然后将这些函数作为第一个参数传递给ApplyA的构造函数,但我想了解如何直接使用高阶多态性。
发布于 2011-11-25 23:04:36
问题是List示例根本不涉及任何高阶多态性。List.apply只接受数量可变的参数:
def apply(xs: A*)高阶多态性涉及方法或类型,它们将类型构造函数作为类型参数,例如
def fmap[F[_], A](x: F[A]): F[B]所以不能,你不能使用高阶多态性。
发布于 2011-12-20 02:53:35
您的List示例不涉及高阶多态性,这一点@alexey_r是非常正确的。但是,如果您准备使用一些type-level heavy artillery,您可以对A{0,1,2}构造函数的多重性进行抽象,以获得与您所要求的内容非常接近的内容。
要注意的第一点是,正如所写的那样,您的“泛型”类不可能被实现,
case class ApplyA(c : ???, l : List[A]) ...因为在编译时,构造函数c的多重性和列表l的长度之间没有可检查的关系。我们可以通过用HList替换List来解决这个问题,并帮助我们自己从具有任意参数的普通函数转换为具有单个HList参数的函数。
import shapeless.HList._
import shapeless.Functions._
sealed abstract class A { def eval() : A }
case class A0 () extends A { def eval() = this }
case class A1 ( a : A ) extends A { def eval() = this }
case class A2 ( a : A, b : A ) extends A { def eval() = this }
case class ApplyA[C, L <: HList, HF](c : C, l : L)
(implicit hl : FnHListerAux[C, HF], ev : HF <:< (L => A)) extends A {
def eval () : A = hl(c)(l)
}
val a : A = A0()
val a0 = ApplyA(A0.apply _, HNil)
val a1 = ApplyA(A1.apply _, a :: HNil)
val a2 = ApplyA(A2.apply _, a :: a :: HNil)隐式参数hl : FnHListerAux[C, HF]提供了从构造函数到来自单个HList参数的函数的转换。隐式参数ev : HF <:< (L => A)证明所提供的构造函数参数的HList的长度是正确的(类型为FWIW,但这在本例中几乎没有关系)。
https://stackoverflow.com/questions/8270526
复制相似问题