How to collapse a collection of endomorphism with cats

For function

def f(i: I) : S => S 

I would like to write a pretty general g combinator

 def g(is : Seq[I], init: S) : S 

In a simple implementation, only classic scala is used

 def g(is : Seq[I], init: S) : S = is.foldLeft(init){ case (acc, i) => f(i)(acc) } 

I tried using Foldable , but I ran into a compilation problem.

 import cats._ import cats.Monoid import cats.implicits._ def g(is : Seq[I], init: S) : S = Foldable[List].foldMap(is.toList)(f _)(init) 

Error

 could not find implicit value for parameter B: cats.Monoid[S => S] 

I managed State

 import cats.data.State import cats.instances.all._ import cats.syntax.traverse._ def g(is : Seq[I], init: S) : S = is.toList.map(i => State.modify(f(i))).sequenceU.runS(init).value 

I have a few questions:

  • Is there a Monoid for endomorphism in cats
  • Can you explain the compilation problem when I use all import expressions together? Is there a trick to easily find the right import?
  • Is State too strong an abstraction in this case?
  • Is there a better way?

[update] I found a workaround for 1.

 type Endo[S] = S => S def g(is : Seq[I], init: S) : S = Foldable[List].foldK[Endo, S](dirs.toList.map(f _)) 

But I still foldMapK to avoid the pattern ...

+5
source share
1 answer

foldMap will not work here, because your f - I => S => S , which does not match the foldMap signature:

 def foldMap[A, B](fa: F[A])(f: (A) ⇒ B)(implicit B: Monoid[B]): B 

you will need your A => B and B => B => B ( Monoid ). f has already combined these two operations. Just use foldLeft .

+3
source

Source: https://habr.com/ru/post/1262185/


All Articles