2017-11-21 20 views
1

私はスカラズを学んでいますが、今はIOモナドの点を理解しようとしています。私はIOモナドについてthis articleを読み、最も単純な例を自分で実行しようとしている:ScalaのIOモナドの理解

val io = println("test").pure[IO] 
println("before") 
io.unsafePerformIO() 

予想通りはい、それは動作します。それは印刷する

before 
test 

しかし、私はIOモナドの要点をキャッチすることはできません。トリックは何ですか?私が参照した記事で指定されているように「置換を維持する」を除いて。

この置換はあまりにも役に立たないようです。説明していただけますか?

私は考えることができます。私はいくつかの特徴を持っている想像:

trait Reader{ 
    def read(): List[Int] 
} 

trait Writer[T]{ 
    def write(t: T): Unit 
} 

は、だから私は(私の場合は List)モナドの値を読み取ることができるリーダーを持っています。そして、コンテナからすべての値をどこか別の場所に書き込んで、トランスフメンテーションを実行する必要があります。その場合、IOモナドは役に立ちますか?

答えて

1

IOはまったく私たちの周りにあります。これは、プログラムを実際に役立つものにしています。なぜなら、私たちは一日中純粋な表現を計算することができないからです。

IOモナドは、たとえばネットワークなどの不純なソースからデータを取り出すなど、IO操作を「不安定」にする問題を解決しようとします。

IOは、それ自体は、参照透過的ではありません。たとえばprintlnのように、Unitを返すメソッドについて考えてみましょう。ちょうどUnit(または())の代わりにprintlnを代用しようとしますが、同じ値を得られませんか? printlnにはという効果があり、コンソールに印刷するのはです。あなたの例を使用して

、想像:私たちは()writeを置換した場合

def write(t: T): Unit 

はどうなるでしょうか?さて、外部ソースに書き込む効果があります。ただし、IO[Unit]を使用した場合は、代理を壊すことはありません。

あなたの問題を実際に見るには、ListのモナドとIOのモナドを組み合わせる必要があります。私たちはモナドが構成していないことを知っています。これは本当にきれいな、おそらくないようにまっすぐ進むだけUnitを返す副作用の操作を呼び出すようではありません

import cats._ 
import cats.data.Nested 
import cats.effect.IO 
import cats.implicits._ 

val nested = Nested(IO.pure(reader.read())) 
val res: Nested[IO, List, IO[Unit]] = 
    Functor[Nested[IO, List, ?]].map(nested)(i => writer.write(i)) 

val ioResult = for { 
    listOfIO <- res.value 
    flattened <- Applicative[IO].sequence(listOfIO) 
} yield flattened 

ioResult.unsafeRunSync() 

、私は良くあります確信している:私たちはモナド変圧器といくつかの策略に頼る必要がありますデモンストレーションの目的のために私がここで作成したものよりもモナド構成を回る方法。

+0

ありがとうございますが、私はIO [List [T]]を変換することに関して何か質問があります。 'Scalaz'は' IO'モナドのための変圧器を持っていますか? 'IoT [T]'を使うのがとても便利でしょう。 –

+2

'IO [List [T]]'を持っているなら、スカラには 'ListT'トランスが必要です。 –