简体   繁体   English

Scala 特征和方法参数的高级类型

[英]Scala Higher Kinded Types for Traits and Method Parameters

I have a trait definition that wraps side effects when instantiated like this:我有一个特征定义,它在像这样实例化时包含副作用:

trait MyTrait[F[_]] {
  def func1(param: Param): F[Param]
}

Where my Param is a case class which itself takes type parameters like this:我的 Param 是 case class,它本身采用如下类型参数:

final case class Param[F[_]] {
  field1: F[String],
  field2: F[Int]
)

Now my question is, what does it mean if I change my trait method signature to the following:现在我的问题是,如果我将特征方法签名更改为以下内容,这意味着什么:

trait MyTrait[F[_]] {
  def func1(param: Param[_]): F[Param[_]]
}

As you can see I'm having a wildcard everywhere I reference the Param case class. Is this a good approach?如您所见,我在引用 Param 案例 class 的所有地方都有通配符。这是一个好方法吗? I do not want to tie my interface to a type expectation on a method param.我不想将我的接口与方法参数上的类型期望联系起来。

As @AndreyTyukin noticed, your code doesn't compile because Param and F don't agree in kinds正如@AndreyTyukin 所注意到的,您的代码无法编译,因为ParamF在种类上不一致

trait MyTrait[F[_]] {
  def func1(param: Param): F[Param]
}
//compile error: class Param takes type parameters

final case class Param[F[_]](
  field1: F[String],
  field2: F[Int]
)

https://scastie.scala-lang.org/DmytroMitin/K2EHGDXERFCJisz45edMsA https://scastie.scala-lang.org/DmytroMitin/K2EHGDXERFCJisz45edMsA

Maybe you meant也许你的意思是

trait MyTrait[F[_]] {
  def func1(param: Param[F]): F[Param[F]]
}

final case class Param[F[_]](
  field1: F[String],
  field2: F[Int]
)

https://scastie.scala-lang.org/DmytroMitin/K2EHGDXERFCJisz45edMsA/1 https://scastie.scala-lang.org/DmytroMitin/K2EHGDXERFCJisz45edMsA/1

func1 return type F[Param[F]] looks like fix point https://free.cofree.io/2017/11/13/recursion/ func1返回类型F[Param[F]]看起来像修复点https://free.cofree.io/2017/11/13/recursion/

Now my question is, what does it mean if I change my trait method signature to the following:现在我的问题是,如果我将特征方法签名更改为以下内容,这意味着什么:

 trait MyTrait[F[_]] { def func1(param: Param[_]): F[Param[_]] }

Instead of Param[F] with current effect F you're starting to use an existential type Param[_] with arbitrary (unknown) effect, possibly different from F .而不是具有当前效果FParam[F]您开始使用具有任意(未知)效果的存在类型Param[_] ,可能与F不同。

What is an existential type? 什么是存在类型?

Is this a good approach?这是一个好方法吗? I do not want to tie my interface to a type expectation on a method param.我不想将我的接口与方法参数上的类型期望联系起来。

Depends on your goal.取决于你的目标。 Does it make sense for your setting that MyTrait and Param will have unconnected effects? MyTraitParam具有不相关的效果对您的设置有意义吗?

For example one of them is going to database while the other is writing to a file on disc.例如,其中一个正在访问数据库,而另一个正在写入磁盘上的文件。 One of them is travelling through time while the other is launching missiles.其中一个正在穿越时空,而另一个正在发射导弹。

If this really makes sense for your setting to work with different effects, consider modifying the signature adding the 2nd effect type (rather than existential) on method level如果这对您的设置使用不同的效果确实有意义,请考虑修改签名,在方法级别添加第二种效果类型(而不是存在的)

trait MyTrait[F[_]] {
  def func1[G[_]](param: Param[G]): F[Param[G]]
}

(Or should it be still F[Param[F]] ? Or G[Param[F]] ? This depends on your setting.) (还是应该仍然是F[Param[F]] ?还是G[Param[F]] ?这取决于您的设置。)

or on type-class level或在类型级别

// (*)
trait MyTrait[F[_], G[_]] {
  def func1(param: Param[G]): F[Param[G]]
}

Or you can even try或者你甚至可以尝试

trait MyTrait[F[_]] {
  def func1[G[_], H[_]](param: Param[G]): F[Param[H]]
}

or要么

trait MyTrait[F[_], G[_], H[_]] {
  def func1(param: Param[G]): F[Param[H]]
}

After new question Type Arguments and Bounds in Scala I'll add here that one more option is to make G an abstract type member rather than method's type parameter.在新问题Type Arguments and Bounds in Scala 之后,我将在此处添加一个选项,即使G成为抽象类型成员而不是方法的类型参数。 Then G must be implemented in inheritors rather than the method must work for arbitrary G .然后G必须在继承者中实现,而不是该方法必须适用于任意G

trait MyTrait[F[_]] {
  type G[_]
  def func1(param: Param[G]): F[Param[G]]
}

It's similar to the above (*), ie having G a type parameter of the type-class.它类似于上面的 (*),即让G成为类型类的类型参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM