自由单子应该基于的那个漏斗在哪里?

问题描述 投票:2回答:1

我试图理解自由单体的概念,我在第一句话上就被绊住了。猫科医生 指出

自由单体是一种结构,它允许你建立一个单体。从任何一个Functor

我的困惑主要在于,在 "释放 "ADT的过程中,并没有使用/created的任何漏斗,以实现 "自由"。KVStoreA. 没有实现ADT的functor或类似的东西。但是,在文档中,对 Free[S[_],A]S 我必须是一个漏斗者。

某个漏斗的自由操作单子 S.

自由单体应该基于的那个漏斗在哪里?

scala functional-programming scala-cats
1个回答
3
投票

问题是,Free monad可以用几种不同的方式来使用。为了使用其中一种方式,你需要假设你有一些漏斗器 S[_],它将有一些 Functor[S] 定义的,你将解除 S[*]Free[S, *] 通过允许某种形式的扩展到原来的 S:

Free[S, A] = S[A] or A

这不是有效的Scala! 它的实际实现方式是使用 ADT. 这只是作为一种理念的解释。

这样,如果你有 S[A] 而你 mapf: A => B您可以使用 Functor[S] 并接受 S[B]. 但如果你 flatMapf: A => Free[S, B]......你仍然可以用以下方法来计算 Functor[S] 并接受 S[Free[S, B]]. 这就是下面这段代码的作用。记住 Free[S, A] = S[A] or A 你可以看到,这将变成 S[S[S[...]]] 如果不是因为这样,它可以无限地嵌套下去 or A 一部分 Free[S, A] 这将让我们在某个时间点停止。

当然我们不会一次计算完毕,Free通常使用trampoline一次只计算一件事,所以我们不会一次就有大量的嵌套结束。

sealed abstract class Free[S[_], A] extends Product with Serializable {
  // ...
}
object Free extends FreeInstances {

  /**
   * Return from the computation with the given value.
   */
  final private[free] case class Pure[S[_], A](a: A) extends Free[S, A]

  /** Suspend the computation with the given suspension. */
  final private[free] case class Suspend[S[_], A](a: S[A]) extends Free[S, A]

  /** Call a subroutine and continue with the given function. */
  final private[free] case class FlatMapped[S[_], B, C](c: Free[S, C], f: C => Free[S, B]) extends Free[S, B]

  ...
}

这个trampoline的表示方法实现了与 S[A] or A 但它允许一步一步地运行计算。它还表明 Free[S, *]S[*] 代数 pureflatMap 操作(对S不做任何假设),这就证明了Free是一个合理的 自由代数.

实际上,在我们决定运行计算之前,我们只有懒惰评估的数据结构。运行它的一种方法是调用 free.run在猫咪中定义为 "免费"。 - 它将使用蹦蹦床来评估这个巢穴的每一个,一次一个,但随后它将使用 Comonad[S] 来提取值--因此我们会在走的时候去掉嵌套。Comonad[S] 也是 Functor[S] 这就是为什么我们不需要单独提供它来做所有这些。maps.

但这是一种运行方式。另一种方式是假设我们记录的是... map, flatMappure 操作使用 Free. 为此,我们不需要 Functor[S] 根本没有。我们可以决定 run 用事 Comonad[S]但我们也可以决定一些其他的事情。如果我们翻译成 S[_] 对某些 M[_]但我们知道,这 M[_]Monad[M]? 在这种情况下,我们就不必使用 Functor[S] 根本不可能! 我们将运行翻译 S ~> M然后,在其上绘制地图或平面地图,并在其上绘制 S 里面的内容会用同样的 S ~> M 机制。这就是 foldMap 是否 - 它要求我们提供一个自然的转变 S ~> M 和实例 Monad[M]Functor[S] 是完全没有必要的。虽然在概念上我们仍然可以认为 S 作为一个漏斗器,我们不需要依赖任何漏斗器的属性,而不是以 Functor[S].

所以最后回答你的问题--当我们还在 "记录操作 "的阶段时,我们不必假设,Free S 是一个漏斗,所以我们不需要用 Functor[S]. 当我们想解释 Free[S, A] 到一些东西中--这就是可能真正需要 functor 的地方,例如,如果我们想运行 Free[S, A] 变成 A. 但对于一些解释,例如 foldMap (这是我认为最流行的解释之一),这是不需要的,因为我们把 S 作为一个纯数据。

© www.soinside.com 2019 - 2024. All rights reserved.