假设我有以下免费monad定义:
sealed trait SetOpsA[A]
case class AllSetNames() extends SetOpsA[Set[String]]
case class IdsFromSet(setName: String) extends SetOpsA[Set[String]]
object SetOps {
type SetOps[A] = Free[SetOpsA, A]
def allSetNames(): SetOps[Set[String]] =
liftF[SetOpsA, Set[String]](AllSetNames())
def idsFromSet(setName: String): SetOps[Set[String]] =
liftF[SetOpsA, Set[String]](IdsFromSet(setName))
}
现在我想检索所有设置名称,然后为每个设置名称执行idsFromSet操作。
我会这样描述:
val prog = for {
allSetNames <- allSetNames()
setName <- allSetNames
ids <- idsFromSet(setName)
} yield ids
但这是不可能的,因为monads不能混在一起进行理解。所以在'setName&lt; - allSetNames'行上,编译器抱怨它被赋予一个Set并且它想要一个Free。
通过环顾四周,看起来monad变压器将成为可能。但是有了这些信息,我真的迷失了,因为我能找到的monad变换器的例子似乎离我的例子太远了,或者我在这个例子中对我的解释太过抽象。所以对此有所帮助将不胜感激。
编辑:我更进了一步,可以通过这样做来实现我的结果(我也意识到我想要扁平的ID,而不是ids集合的集合):
val prog = for {
allSetNames <- allSetNames()
ids <- allSetNames.toList.traverseU(idsFromSet)
} yield ids.flatten