1

可以说我有以下免费的单子定义:

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

但这是不可能的,因为单子不能混入理解中。所以在'setName <- allSetNames'这一行上,编译器抱怨它被赋予了一个Set并且它想要一个Free。

通过环顾四周,单子变压器似乎是要走的路。但是有了这些信息,我真的迷失了,因为我能找到的带有 monad 转换器的示例似乎与我的示例相距太远,或者解释太抽象而无法在此示例中实现。因此,我们将不胜感激。

编辑:我更进一步,可以通过这样做来实现我的结果(我也意识到我想要扁平的 id,而不是 id 的集合):

val prog = for {
  allSetNames <- allSetNames()
  ids <-  allSetNames.toList.traverseU(idsFromSet)
} yield ids.flatten
4

0 回答 0