我一直在编写我自己的 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
}
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
就像一个函数,你不能折叠它也不能遍历它。