2017-11-21 20 views
1

스 카스를 배우고 있으며 이제는 모나드 IO의 요지를 이해하려고합니다. 나는 입출력 모나드에 대한 this article를 읽고 간단한 예에게 자신을 실행하려고 : 예상대로스칼라의 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 Monad를 유용하게 사용할 수 있습니까?

답변

1

IO는 하루 종일 순수한 표현을 계산할 수 없으므로 프로그램을 실제로 유용하게 만드는 요소입니다.

IO 모나드는 예를 들어 네트워크와 같은 불순한 소스에서 데이터를 가져 오는 것과 같이 IO 작동을 "확실하지 않게"하는 문제를 해결하려고합니다.

IO는 그 자체로서 명확하게 투명하지 않습니다. 예를 들어 println과 같은 Unit을 반환하는 메소드에 대해 생각해보세요. Unit (또는 ())을 println으로 바꾸려고합니다. 동일한 값을 얻지는 못하겠습니까? println에는 콘솔에 인쇄 할의 효과가 있습니다. 귀하의 예제를 사용

, 상상 : 우리가 ()write 교체하는 경우

def write(t: T): Unit 

은 어떻게 될까? 음, 외부 소스에 글을 쓰면 효과가 있습니다. 그러나 IO[Unit]을 사용하면 대체를 위반하지 않습니다.

실제로 문제를 살펴 보려면 List 모나드와 IO 모나드를 조합해야하며 모나드는 작성하지 않습니다. 우리는 모나드 변압기와 약간의 속임수에 의지해야합니다 :

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() 

이 정말 예쁜하지 않고, 아마 정직처럼 Unit을 돌아가는 effectful 작업을 호출하지,하지만 난 거기에 더 나은 확신 해요 데모 목적으로 여기에서 만든 것보다 모나드 구성을 돌아 다니는 방법.

+0

감사합니다.하지만 IO [List [T]]를 변형하는 것에 대해 질문이 있습니다. 'Scalaz'는'IO' 모나드 용 변압기를 가지고 있습니까? 'IoT [T]'를 사용하는 것이 매우 편리 할 것입니다. –

+2

만약 IO [List [T]]가 있다면 당신은 scalat에있는'ListT' 변환기가 필요합니다. –