为采用带有类型参数的方法的类型类定义构造函数?

问题描述

我遇到的一种情况是,我所知道的所有解决方案都不像是好的解决方案。我试图定义一个类型类,如下面的示例所示,它具有抽象类型S,该类型必须实现另一个类型类(未显示Valid[A]。感觉最简单的方法是创建一个apply构造函数,该构造函数将强制用户输入S自动sIsValid引入一个隐式实例。

此问题是函数changeType带有类型参数。尽管进行了一些谷歌搜索,但我还没有弄清楚如何为带有类型参数的函数编写类型注释(这可能是因为Scala不允许使用带有类型参数的匿名函数)。我的方法在这里看来是明智的吗?如果我可以为changeType提供类型注释,则类型类用户仍可以将非匿名函数传递给apply构造函数,这似乎是一个令人满意的解决方案。

abstract class IsTC[A[_],T] {
  // type S is an abstract type rather than type parameter,but must implement Valid[A]
  type S
  implicit val sIsValid: Valid[S]

  def get(self: A[T],i: Int): T
  def changeType[_T]: A[_T]
}
object IsTC {
  def apply[A[_],T,_S](
    fget: (A[T],Int) => T,fchangeType:  // what should this type annotation be?
  ): IsTC[A,T] { type S = _S } = new IsTC[A,T] {
    type S = _S
    def get(self: A[T],i: Int) = fget(self,i)
    def changeType[_T]: A[_T] = fchangeType[_T]
  }
}

感谢您的任何帮助/想法。

解决方法

Scala 2不支持多态函数。多态可以是方法,而不是值。和函数are的值。可以使用包装器仿真多态函数

// for [A] => (a: A) => B[A]
trait Poly {
  def apply[A](a: A): B[A]
}

// for [A <: U] => (a: A) => B[A]
trait Poly[U] {
  def apply[A <: U](a: A): B[A]
}

类似于shapeless.Poly。它们概括了普通函数

trait Function[A,B] {
  def apply(a: A): B
}

尝试

object IsTC {
  def apply[A[_],T,_S](
                          fget: (A[T],Int) => T,fchangeType: FchangeType[A]
                        ): IsTC[A,T] { type S = _S } = new IsTC[A,T] {
    override type S = _S
    override implicit val sIsValid: Valid[_S] = ???
    override def get(self: A[T],i: Int) = fget(self,i)
    override def changeType[_T]: A[_T] = fchangeType[_T]
  }
}

trait FchangeType[A[_]] {
  def apply[X]: A[X]
}

多态函数类型为[A <: U] => (a: A) => f[A](a)的Dotty has多态函数[A <: U] => A => B[A],但是有implementation restriction: polymorphic function types must have a value parameter,因此您不能拥有多态函数类型[X] => A[X]({{ 3}},目前甚至在那里的类型为lambda [X] =>> A[X]

(除了使用包装程序进行仿真之外)某些多态类型也可以通过存在性类型表示:[A] => B[A] => C(对于常量C)实际上是B[_] => C

这是因为∀a: (B(a) => C)(∃a: B(a)) => C