2012-12-11 10 views
7

私はScalaコードで、とりわけスレッド状態のMonadicスタイルの使用を開始する予定です。ここでは3つのモナドの機能を組み合わせること(副作用についてのみ思いやり)の簡単な例Scalaz - リストと州のモナドを組み合わせて理解する

import scalaz._ 
import Scalaz._ 

object MonadTest { 
    def adder(i: Int) = State[String, Int] ({str: String => (str + i.toString + " ", i) }) 
    val oneTwoThreeMonad = for { 
    m1 <- adder(1) 
    m2 <- adder(2) 
    m3 <- adder(3) 
    } yield m3 
    oneTwoThreeMonad("start: ")._1 //String = "start: 1 2 3 " 
} 

だ。このすべては一目瞭然で、期待通りに動作します。しかし、私にとってこのアプローチが本当に便利であるためには、それをListと組み合わせることができるようにしたいと考えています。ここで私が何を意味するか表示する(動作しない)コードのビットです:

val list = List(1, 2, 3) 

val oneTwoThreeBis = for { 
    i <- list 
    mx <- adder(i) 
} yield mx 

基本的に私はListからの引数に基づいてモナドを組み合わせることができるようにしたい - の各要素に単項関数を実行しますlistと私は行くように副作用を蓄積する。私はこの例の構文がうまくいかないと理解しています。なぜそうでないのか分かります。私はちょうどきれいでエレガントなものを探しています。

scalazモナド変圧器を使用して、具体的にはStateTを使用してこれを実現することは可能でしょうが、どのようにすればよいかわかりません。

PS。私はScalaz 7.0-M3を使用しているので、シンタックスは最も一般的な6.xと少し異なるかもしれません。

答えて

9

私は私はあなたが探している正確に何を理解していないが、あなたが望むように聞こえるより(traverseはHaskellのmapMのより一般的なバージョンである)、ここでtraverseのようなもの:

import scalaz._, Scalaz._ 

def adder(i: Int) = State[String, Int](str => (str + i.toString + " ", i)) 

List(1, 2, 3).traverseS(adder)("start: ")._1 

は、予想通りこれは、次のように出力されます:私はWRIすることを避けるためにtraverseSを(Stateための場所Sスタンド)を使用してい

res0: String = "start: 1 2 3 " 

注意をむしろ面倒な型パラメータを取り除きますが、traverseは、モナディック関数をトラバース可能なものにマップする必要があるときに、より一般的に便利です。

StateTの例は、これがあなたが望んでいない場合は喜んでお待ちしておりますが、それはあなたのタイプがList[(String, Int)]であることになります。

+0

私が探しているもののように見えます。しかし実際には状態変圧器を実際に使用することを覚えなくてはならないという事実は変わらない; – nietaki

+1

私はすでに 'traverse'と' traverseS'の詳細な記述あなたにもそれを賞賛しました。私はそれが私と一緒にいかなかったかを想像することはできません... – nietaki

+1

誰かがScalazではなくCatsと似たようなことをする必要があるならば、 'traverseS'はありませんが、' traverseS'を使用して:https://github.com/benhutchison/gesture/blob/master/core/jvm/src/test/scala/gesture/GestureProcessorSpec.scala#L34 –

関連する問題