7

Haskell 中的 Free 实现是:

data Free f a =
Pure a
| Free (f (Free f a))

而Scalaz中的实现是:

sealed abstract class Free[S[_], A]

private case class Return[S[_], A](a: A) extends Free[S, A]
private case class Suspend[S[_], A](a: S[A]) extends Free[S, A]
private case class Gosub[S[_], B, C](a: Free[S, C], f: C => Free[S, B]) extends Free[S, B]

为什么 scalaz 实现不类似于 Haskell,例如:

sealed trait Free[F[_],A]
case class Return[F[_],A](a: A) extends Free[F,A]
case class GoSub[F[_],A](s: F[Free[F,A]]) extends Free[F,A]

这两个实现是同构的吗?

4

1 回答 1

7

将该 Haskell 代码转换为 Scala 将是

sealed abstract class Free[S[_], A]

case class Return[S[_], A](a: A) extends Free[S, A]
case class Suspend[S[_], A](a: S[Free[S, A]]) extends Free[S, A]

Gosub由于惰性评估,Haskell 实现不需要这种情况。这种表示也可以在 Scala 中工作,但由于(严格评估和)缺乏尾调用消除,它会导致堆栈溢出问题。为了使其堆栈安全,我们flatMap懒惰地表示为Gosub(我认为FlatMap这会是一个更好的名字):

case class Gosub[S[_], B, C](a: Free[S, C], f: C => Free[S, B]) extends Free[S, B]

作为奖励,引入Gosub允许我们简化Suspend

case class Suspend[S[_], A](a: S[A]) extends Free[S, A]

因为我们不再需要flatMap通过映射 s 的内容来做S[_]s——我们将flatMaps 明确表示为Gosubs。

因此,与 Haskell 表示不同,这种结果表示允许我们做任何想做的事情,Free而无需Functor[S]. 因此,当我们S不是Functor.

于 2016-06-10T18:57:18.347 回答