Mar*_*ger 7 polymorphism scala
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)
Run Code Online (Sandbox Code Playgroud)
换句话说,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 { ... }
....
Run Code Online (Sandbox Code Playgroud)
所以我有一堆case类,子类A,其构造函数不一定采用相同数量的参数.我也希望有一个'通用'案例类,如下所示:
case class ApplyA ( c : ???, l : List [ A ] ) extends A {
def eval () : A = { ??? } }
Run Code Online (Sandbox Code Playgroud)
这个想法是ApplyA将第一个参数作为一个构造函数,它是一个子类型A和一个参数列表.eval然后,如果可能,该方法使用构造函数构造适当的类(即列表具有正确的长度)并返回它(这对应l ( 1, 2, 3)于List上面的示例).第一个构造函数的参数类型是ApplyA什么?
这应该可以使用更高阶的多态性,但我无法弄清楚如何.我知道即使不使用高阶多态,只需将构造函数包装在函数中,然后将这些函数作为第一个参数传递给构造函数,我就可以做到这一点ApplyA,但我想了解如何直接使用高阶多态.
Mil*_*bin 13
@alexey_r非常正确,您的List示例不涉及高阶多态.但是如果你准备使用某种类型级别的重型火炮,你可以抽象你的A{0,1,2}构造者的arity 来获得看起来非常接近你所要求的东西.
要注意的第一点是,正如所写的那样,你的"通用"类不可能被实现,
case class ApplyA(c : ???, l : List[A]) ...
Run Code Online (Sandbox Code Playgroud)
因为构造函数的arity c和列表的长度之间没有编译时可检查的关系l.我们可以通过替换Lista HList并帮助自己从具有任意arity的普通函数转换为具有单个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)
Run Code Online (Sandbox Code Playgroud)
隐式参数hl : FnHListerAux[C, HF]提供了从构造函数(无论它是什么)到单个HList参数的函数的转换.隐式参数ev : HF <:< (L => A)证明提供HList的构造函数参数的长度具有正确的长度(并且类型为FWIW,但在此示例中几乎不相关).
问题是该List示例根本不涉及任何高阶多态.List.apply只需要可变数量的参数:
def apply(xs: A*)
Run Code Online (Sandbox Code Playgroud)
高阶多态性涉及将类型构造函数作为类型参数的方法或类型,例如
def fmap[F[_], A](x: F[A]): F[B]
Run Code Online (Sandbox Code Playgroud)
所以不,你不能使用高阶多态.