我正在做一些可能會失敗的計算,所以我使用了析取類型作爲結果。我有我已經寫了下面的功能相當常見的模式:如何使用組合器嵌入分離器的作家monad摺疊序列?
def traverse[A, B, E](a: Iterable[A], b: B)(f: (B, A) => E \/ B): E \/ B =
a.foldLeft[E\/B](\/-(b)){case (b0, a0) => b0 flatMap (f(_, a0))}
但現在我要記錄的計算(均以失敗或成功的情況下)。我需要一個以下類型的函數:
type Logged[T] = scalaz.Writer[String,T]
def traverseLogged[A, B, E]
(a: Iterable[A], lb: Logged[B])
(f: (Logged[B], A) => Logged[E \/ B]): Logged[E \/ B]
但是我找不到依賴於combinators的「很好的實現」。我想出了以下實現:
a.foldLeft[Logged[E \/ B]](lb.map(_.right[E])){
(lb0, a0) =>
val (log, value) = lb0.run
value match {
case -\/(err) => lb0
case \/-(b) => f(b.set(log),a0)
}
}
有沒有一種方法來實現它,而不必運行記錄的b?
PS:我希望這個問題的標題是足夠清晰的> _ <
非常感謝!我確信我的「遍歷」已經在scalaz中,但我沒有設法找到它。 對於traverseLogged,我需要在摺疊過程中對日誌進行線程化,因此我無法直接使用您的解決方案。然而,你給了我一些很好的咀嚼。我將在明天進一步研究。 (這裏有點晚) 再次,非常感謝! – lorilan
好吧,我用一種新鮮的頭腦再次審視它。我設法實現了與您的「traverseLogged」幾乎相同的功能: http:// pastebin。然而,所有這些層次的變化似乎有點奇怪。其實我的B型是一個圖表,我做了一些轉換(可能會失敗)。但棘手的部分是,這些轉換中的一些可能是相互遞歸的,所以我需要改變級別。這些級別的變化是否正常,還是我需要更多地關注升級系列的功能(仍然是scalaz新手:p),還是我必須製作自定義類型,monad混合析取和作者? – lorilan