假设有一个函数
def f(i: I) : S => S
我想编写一个相当常见的组合器 g
def g(is : Seq[I], init: S) : S
简单的实现只使用经典的Scala。
def g(is : Seq[I], init: S) : S =
is.foldLeft(init){ case (acc, i) => f(i)(acc) }
我尝试使用Foldable
,但遇到了编译问题。
import cats._
import cats.Monoid
import cats.implicits._
def g(is : Seq[I], init: S) : S =
Foldable[List].foldMap(is.toList)(f _)(init)
错误是:
could not find implicit value for parameter B: cats.Monoid[S => S]
我使用了
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
我有几个问题:
- 在cats中,是否有一个用于自同态的Monoid?
- 当我同时使用所有import语句时,能否解释编译问题?是否有技巧可以轻松找到正确的import?
- 在这种情况下,State是否是一个过于强大的抽象?
- 是否有更好的方法?
[更新] 我已经找到了1的解决方法。
type Endo[S] = S => S
def g(is : Seq[I], init: S) : S
= Foldable[List].foldK[Endo, S](dirs.toList.map(f _))
但是我仍然需要使用foldMapK
来避免样板代码...
Monoid
实例:Foldable[List].foldMap(is.toList)(f _)(MonoidK[Endo].algebra)(init)
。 - Peter Neyens