在学习函数式编程和探索延续的概念时,我熟悉了类型(monad 转换器)Co密度和 ContT。 它们看起来很相似,但仍不清楚它们之间的关系。 看起来 Co密度比 ContT 更主要,不是吗?
在Scala 3中,此类类型可以这样写:
type Codensity = [F[_]] =>> [A] =>> [B] => (A => F[B]) => F[B]
type ContT = [F[_]] =>> [A, B] =>> (A => F[B]) => F[B]
当Co密度指定时,如何推断ContT的类型(假设我们事先不知道ContT是什么)? 有何理由? 或者一种类型基于另一种类型的其他推论?
你是对的。区别不仅仅在于柯里化。
指定Co密度时如何推断ContT的类型
在更简单的情况下你会如何回答你的问题?
type X = [A] =>> List[A]
type Y = [A] => () => List[A] // it would be better to write [A] => List[A] but it's forbidden in Scala for technical reasons
“当指定
X
时,如何推断Y
的类型?”
X
是依赖于 A
的类型。 Y
是一种类型,其项(值)取决于 A
。
X
是List
。 Y
例如 Nil[A]
。
(如果我们考虑不变列表,即
sealed trait List[A]
case class Cons[A](head: A, tail: List[A]) extends List[A]
case class Nil[A]() extends List[A]
而不是
sealed trait List[+A]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]
)
两种类型之间的关系如下。对于
Y
类型的值,应用于 A
的该值属于应用于 X
的 A
类型。
type ContT = [F[_]] =>> [A, B] =>> (A => F[B]) => F[B]
type Codensity = [F[_]] =>> [A] =>> [B] => (A => F[B]) => F[B]
这里为了获得正确的类型(即
*
的类型),对于ContT
我们必须修复F
,A
,B
,对于Codensity
我们必须修复F
,A
。
[B] =>> (A => F[B]) => F[B]
是依赖于 B
的类型。 [B] => (A => F[B]) => F[B]
是一种类型,其项取决于 B
。
两种类型之间的关系如下。对于
Codensity[F][A]
类型的值,应用于 B
的该值属于 ContT[F][A, B]
类型
type F[_]
type A
type B
type X = ContT[F][A, B]
val x: X = ???
type Y = Codensity[F][A]
val y: Y = ???
y[B]: X