2013-04-23 4 views
2

이 질문은 훨씬 간단 경우이 다른 question 관련이 있지만, 감소scalaz 트램폴린 및 IO

import scalaz._, Scalaz._ 
import Free._, effect._ 

나는 다음과 같은 발전기가 :

val fromOneIO:() => IO[Int] = { 
    var i = 0;() => { i += 1; IO(i) } 
} 
val fromOne:() => Int = { 
    var i = 0;() => { i += 1; i } 
} 

및 다음과 같은 비 꼬리 재귀 정의 :

def rec(i: Int): Int = { 
    if (i == 0) { 
    fromOne() 
    } else { 
    rec(i - 1) + fromOne() 
    } 
} 
def rec1(i: Int): Trampoline[Int] = { 
    if (i == 0) { 
    Return(fromOne()) 
    } else { 
    suspend { 
     for { 
     a <- rec1(i - 1) 
     b <- Return(fromOne()): Trampoline[Int] 
     } yield a + b 
    } 
    } 
} 
def recio(i: Int): Trampoline[IO[Int]] = { 
    if (i == 0) { 
    Return(fromOneIO()) 
    } else { 
    suspend { 
     for { 
     ioa <- recio(i - 1) 
     iob <- Return(fromOneIO()): Trampoline[IO[Int]] 
     } yield { 
     for (a <- ioa; b <- iob) yield a + b 
     } 
    } 
    } 
} 

결과는 다음과 같습니다

rec(100) // overflows for arg 10000 
rec1(10000).run // works 
recio(10000).run.unsafePerformIO() //overflows 

어떻게 IO지도 /뿐만 아니라 trampolined 수 flatMap하게 관리 할 수? 그것은 다른 중첩 된 스택 내면 이해를 위해 만든 것 같습니다. unsafePerformIO을 사용할 TrampolineT을 작성하고 추출 된 io 값을 일시 중단에 다시 랩핑해야합니까?

+0

이 특정 예에서'IO [A : Monoid]'에 대한'Monoid' 인스턴스가 작동하는 것 같습니다. 즉, 'yield'문을'ioa | + | '로 변경하면됩니다. iob'. 나는 더 넓은 그림을 위해 추천 할 아무것도 가지지 않고있다. – folone

+0

사실, 문제는'IO'에 대한'Monad' 인스턴스에있는 것 같습니다. 'Applicative' 인스턴스를 사용하면 잘 작동하는 것 같습니다. 'yield (ioa | @ | iob) {_ + _}' – folone

+0

'IO' 자체가 트램 폴린되기를 원한다. 당신의 코드는 스택 오버 플로우없이'IO' 액션을 구현할 수있게 해줍니다.하지만 당신이 그것을 빌드하는 방법은'IO' 액션을 실행할 때 스택 오버플로를 일으킬 것입니다. –

답변

3

그래서 IO(_)은 이미 trampolined입니다. folone에서 제안뿐만 아니라,이 같은에 대한 두 번째를 변경하여 오버 플로우를 피할 수 있어요 :

val s = for (a <- ioa; b <- iob) yield a + b val s1 = s.unsafePerformIO() IO(s1) 

또는 같은

: 또한

IO(for (a <- ioa; b <- iob) yield a + b).flatMap(identity) 

IO(_) 소요 이름 매개 변수에 의해 이므로 IO(expr)val e = expr; IO(e)은 동일하게 동작하지 않습니다. 이것은 넘칠 것입니다!

val s = for (a <- ioa; b <- iob) yield a + b 
IO(s.unsafePerformIO()) 

그래서 매우 만족스러운 대답하지 비록 그것이 스택을 불어로 해결 될 또 다른 IO 및 플래트 닝에 실용적 가능한 또는 포장을 사용하는 것 같다.