[英]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 所注意到的,您的代码无法编译,因为
Param
和F
在种类上不一致
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
.而不是具有当前效果
F
的Param[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? MyTrait
和Param
具有不相关的效果对您的设置有意义吗?
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.