首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala构造函数抽象

Scala构造函数抽象
EN

Stack Overflow用户
提问于 2011-11-25 22:31:10
回答 2查看 1.1K关注 0票数 7

在Scala中可以实现以下功能:

代码语言:javascript
复制
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具有更高阶的多态性。我想使用高阶多态性来做以下事情。

代码语言:javascript
复制
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类,就像这样:

代码语言:javascript
复制
case class ApplyA ( c : ???, l : List [ A ] ) extends A {
   def eval () : A = { ??? } }

其思想是,ApplyAA的子类型的构造函数和一组参数作为第一个参数。然后,如果可能,eval方法使用构造函数构造一个合适的类(即列表具有正确的长度)并返回它(这对应于上面List示例中的l ( 1, 2, 3) )。ApplyA的第一个构造函数的参数类型是什么

对于高阶多态性,这应该是可能的,但我不知道如何实现。我知道,即使不使用高阶多态性也可以做到这一点,只需将构造函数包装在函数中,然后将这些函数作为第一个参数传递给ApplyA的构造函数,但我想了解如何直接使用高阶多态性。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-25 23:04:36

问题是List示例根本不涉及任何高阶多态性。List.apply只接受数量可变的参数:

代码语言:javascript
复制
def apply(xs: A*)

高阶多态性涉及方法或类型,它们将类型构造函数作为类型参数,例如

代码语言:javascript
复制
def fmap[F[_], A](x: F[A]): F[B]

所以不能,你不能使用高阶多态性。

票数 9
EN

Stack Overflow用户

发布于 2011-12-20 02:53:35

您的List示例不涉及高阶多态性,这一点@alexey_r是非常正确的。但是,如果您准备使用一些type-level heavy artillery,您可以对A{0,1,2}构造函数的多重性进行抽象,以获得与您所要求的内容非常接近的内容。

要注意的第一点是,正如所写的那样,您的“泛型”类不可能被实现,

代码语言:javascript
复制
case class ApplyA(c : ???, l : List[A]) ...

因为在编译时,构造函数c的多重性和列表l的长度之间没有可检查的关系。我们可以通过用HList替换List来解决这个问题,并帮助我们自己从具有任意参数的普通函数转换为具有单个HList参数的函数。

代码语言:javascript
复制
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,但这在本例中几乎没有关系)。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8270526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档