I've been writing my own version of Scala Cats (to assist others when learning this library). I've implemented my own versions of most type classes, but am stuck with a custom implementation of Traverse for State. The function to implement is:
def traverse[G[_]: Applicative, S, A, B](fa: State[S, A])(f: A => G[B]): G[State[S, B]]
As a starter, I asked ChatGPT for an implementation in Scala Cats (since of course, it does not know my own library). A valid (simple) implementation in Cats should help me write a version in my own library. However, ChatGPT has failed me, with over-complicated solutions using the likes of StateT (of which currently I do not have an equivalent in my library). Also, the versions produced by ChatGPT do not compile.
One simple suggestion is the following, but does not compile:
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
}
Every
Traversable(Traversein Cats) isFoldable.StateisApplicativeandMonadbut notFoldableorTraversableWhy isn't the state monad traversable?
Are there non-trivial Foldable or Traversable instances that don't look like containers? (answer)
You can check that in Cats summoning
Applicative[State[S, *]]andMonad[State[S, *]]compile butFoldable[State[S, *]]orTraverse[State[S, *]]doesn't.State[S, A]is basically a functionS => (S, A)(if we ignore wrapping,StateT, andEval).If
Statewere aFoldableyou'd be able to implementIf
Statewere aTraversableyou'd be able to implementCombining
S => (S, A)andA => G[B]you can haveS => (S, G[B])but how to getG[S => (S, B)]if you only can dodef ap[A, B](ff: G[A => B])(fa: G[A]): G[B]anddef pure[A](x: A): G[A]?Foldablemeans you can fold a structure into a value.Traversablemeans you can traverse a structure executing some applicative effect in every node of the structure.Stateis like a function, you can't fold it or traverse it.