为状态实施 Scala Cats Traverse

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

我一直在编写我自己的 Scala Cats 版本(以帮助其他人学习这个库)。 我已经实现了我自己的大多数类型类版本,但仍然坚持使用 Traverse for State 的自定义实现。要实现的功能是:

def traverse[G[_]: Applicative, S, A, B](fa: State[S, A])(f: A => G[B]): G[State[S, B]]

作为初学者,我向 ChatGPT 询问了在 Scala Cats 中的实现(当然,因为它不知道我自己的库)。 Cats 中的有效(简单)实现应该可以帮助我在自己的库中编写一个版本。 然而,ChatGPT 却让我失望了,因为使用 StateT 之类的解决方案过于复杂(目前我的库中没有类似的解决方案)。 此外,ChatGPT 生成的版本无法编译。

一个简单的建议如下,但不编译:

import cats._
import cats.implicits._

def traverse[G[_]: Applicative, S, A, B](fa: State[S, A])(f: A => G[B]): G[State[S, B]] = {
  val gb: G[B] =
    fa.runA _ andThen f

  val stateB: G[State[S, B]] =
    gb.map(b => State(s => (s, b)))

  stateB
}
scala scala-cats
1个回答
0
投票

State
Applicative
Monad
但不是
Foldable
Traversable
Traverse
在猫中)

为什么状态单子不可遍历?

是否有看起来不像容器的非平凡的 Foldable 或 Traversable 实例?answer

您可以检查猫召唤

Applicative[State[S, *]]
Monad[State[S, *]]
编译但
Foldable[State[S, *]]
Traverse[State[S, *]]
没有。

State[S, A]
基本上是一个函数
S => (S, A)
(如果我们忽略包装、
StateT
Eval
)。

如果

State
是一个
Foldable
你就可以实现

def foldMap[A, B: Monoid](fa: S => (S, A))(f: A => B): B

如果

State
是一个
Traversable
你就可以实现

def traverse[G[_]: Applicative, S, A, B](fa: S => (S, A))(f: A => G[B]): G[S => (S, B)]

Foldable
表示您可以将结构折叠成值。
Traversable
表示您可以遍历结构,在结构的每个节点中执行一些应用效果。
State
就像一个函数,你不能折叠它也不能遍历它。

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