我想为遵循某些约束的参数化函数定义一个新类型。类似的东西:
import scala.util.Try
type Bound = Any
trait T1 {
def apply[A <: Bound](a: A): Try[A]
}
这是有效的,但定义类型T1
的函数的唯一方法是例如。
val t1: T1 = new T1 {
override def apply[A](a: A): Try[A] = Try(a)
}
这有点麻烦。编写类似内容的更合适的方法是使用函数文字。
有办法吗?
请记住定义类似的类型:
trait T2[A <: Bound] extends (A => Try[A])
将无效,因为该类型的每个实例都必须定义类型参数,牺牲已定义实例的genericness
。
val t: T2[Int] = (a: Int) => Success(a)
答案 0 :(得分:1)
(未经测试,只是一个可能有用的想法)
我不清楚Scala中的简明语法。
但是,如果您愿意稍微概括T1
,那么有些插件会尝试解决您问题的稍微更一般的版本。
你要问的是:&#34;是否有自然变换的内联语法&#34;:
trait T1[F[_], G[_]] {
def apply[A <: UpperBound](x: F[A]): G[A]
}
在您的情况下,F
为Id
,G
为Try
,此外,您对A
有约束。这种模式相当常见,因此例如here建议您使用非/ kind-projector编译器插件来实现这种情况。这将允许你写这个:
val t1 = λ[T1[Id, Try]](bodyOfTheApplyMethod)
在documentation of non/kind-projector compiler plugin中,列出了几项要求可行的要求。特别是,T1
确实需要由两个类型构造函数F
和G
进行参数化。而且,我不确定在重写期间插入正确位置的类型是否足够聪明。
话虽如此,我只是和
一起去val t1 = new T1 {
def apply[X <: Bound](x: X): Try[X] = body
}
我认为以最佳方式解决您的具体问题,您必须修改非/ kind-projector插件。或者等待dotty的未来版本。或者切换到具有依赖类型的语言,其中类型参数和普通参数之间没有太大区别。
或者只是按原样接受并使用new ... { def ... }
- 语法。
答案 1 :(得分:0)
这应该可以使用配套对象:
import scala.util.{Success, Try}
type Bound = Any
trait T1[A <: Bound] {
def apply(a: A): Try[A]
}
object T1 {
def apply[A <: Bound](f: A => Try[A]) = {
new T1[A] {
override def apply(a: A): Try[A] = f(a)
}
}
}
val t1 = T1( (a: Int) => Success(a) )
但是我担心它与您特别不想使用的trait T2[A <: Bound]
解决方案完全相同 - 以这种方式创建的函数不再是通用的。
我担心使用apply
的通用T1
成员的方法注定要失败,因为使用该接口,您承诺提供通用功能。没有办法用文字来满足这个承诺,Scala 2.12 SAM不会改变它。