꼬리 호출을 지원하기 위해 ackermann 함수의 변형을 변환하는 방법은 무엇입니까?

피스 송

나는 현재 스택이 오버플로되지 않도록 꼬리 호출 최적화를 지원하는 스칼라에서 ackermann 함수의 변형을 구현하는 문제를 해결하고 있습니다.

문제는 테일 콜을 최적화하는 방법을 찾을 수 없다는 것입니다. continuation-pass-style (CPS)이 도움이 될 것이라고 들었지만 CPS 스타일로 성공적으로 다시 구현했지만 여전히 길을 잃었습니다.

ackermann 함수의 변형은 다음과 같습니다.

ppa(p, a, b) = p(a, b)               (if a <= 0 or b <= 0)
ppa(p, a, b) = p(a, ppa(p, a-1, b))  (if p(a, b) is even and a, b > 0)
ppa(p, a, b) = p(ppa(p, a, b-1), b)  (if p(a, b) is odd and a, b > 0)

최적화가없는 코드는 다음과 같습니다.

def ppa(p: (Int, Int) => Int, a: Int, b: Int): Int = {
  def ppa_cont(a: Int, b: Int, ret: (Int, Int) => Int): Int = {
    if (a <= 0 || b <= 0) ret(a, b)
    else (a, b) match {
      case (_, _) if (p(a, b) % 2 == 0) => ret(a, ppa_cont(a-1, b, (x, y) => ret(x, y)))
      case (_, _) => ret(ppa_cont(a, b-1, (x, y) => ret(x, y)), b)
    }
  }

  ppa_cont(a, b, p)
}

또 다른 시험은 다음과 같습니다.

def ppa(p: (Int, Int) => Int, a: Int, b: Int): Int = {
  def ppa_cont(a: Int, b: Int, cont: (Int, Int) => Int): (Int, Int) => Int = {
    if (a <= 0 || b <= 0) cont
    else if (p(a, b) % 2 == 0) (a, b) => cont(a, ppa_cont(a-1, b, cont)(a-1, b))
    else (a, b) => cont(ppa_cont(a, b-1, cont)(a, b-1), b)
  }
 
  ppa_cont(a, b, p)(a, b)
}

나는 다음과 같이 꼬리 호출을 최적화하려고했습니다.

def ppa(p: (Int, Int) => Int, a: Int, b: Int): Int = {
  @annotation.tailrec
  def ppa_cont(a: Int, b: Int, ret: (Int, Int) => TailRec[Int]): TailRec[Int] = {
    if (a <= 0 || b <= 0) tailcall(ret(a, b))
    else (a, b) match {
      case (_, _) if (p(a, b) % 2 == 0) => {
        tailcall(ret(a, ppa_cont(a-1, b, (x, y) => ret(x-1, y))))
      }
      case (_, _) => {
        tailcall(ret(ppa_cont(a, b-1, (x, y) => ret(x, y-1)), b))
      }
    }
  }

  val lifted: (Int, Int) => TailRec[Int] = (x, y) => done(p(x, y))

  ppa_cont(a, b, lifted).result
}

그러나 이것은 유형 불일치로 인해 컴파일되지 않습니다.

무엇이 문제일까요? 내가 잘못된 방향으로 가고 있습니까? 약간의 힌트와 도움의 손길을 주시면 감사하겠습니다. 고마워 :)

추신 : 힌트를 얻었습니다 : 왜 스칼라가 꼬리 호출 최적화를하지 않습니까?

드미트로 미틴

시도 cats.free.Trampolinescala.util.control.TailCalls.TailRec. @tailrec스택에 안전 하지는 않습니다 .

import scala.util.control.TailCalls._

def ppa(p: (Int, Int) => Int, a: Int, b: Int): Int = {
  def hlp(a: Int, b: Int): TailRec[Int] = {
    if (a <= 0 || b <= 0) done(p(a, b))
    else if (p(a, b) % 2 == 0) tailcall(hlp(a - 1, b)).map(p(a, _))
    else tailcall(hlp(a, b - 1)).map(p(_, b))
  }

  hlp(a, b).result
}

http://eed3si9n.com/herding-cats/stackless-scala-with-free-monads.html

http://eed3si9n.com/herding-cats/tail-recursive-monads.html

실제로 귀하의 기능은 Ackermann처럼 보이지 않습니다. 실제 Ackermann은 두 번의 재귀 호출을합니다.

f(m, n) = f(m - 1, f(m, n - 1))

함수는 단일 재귀 호출을 만듭니다. 함수의 반복 버전을 작성하는 것은 어렵지 않습니다 (컴파일러가 자동으로 반복 버전으로 변환 할 수 있기 때문에 보통 꼬리 재귀가 사용됩니다). , (노란색 영역)에 ppa(i, j)대해 이미 계산했다고 가정 합니다. 그런 다음 두 개의 주황색 세그먼트 (이 순서)와 (이 순서)를 계산합니다. 그런 다음 적혈구를 계산 합니다.0 <= i <= a - 10 <= j <= b - 1(a, 0), (a, 1), ..., (a, b - 1)(0, b), (1, b), ..., (a - 1, b)(a, b)

여기에 이미지 설명 입력

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

환경 변수로 호출을 하위 처리하는 방법은 무엇입니까?

분류에서Dev

useEffect 후크에 의해 호출되는 함수 호출을 중지하기 위해`onClick` 이벤트를 사용하는 방법은 무엇입니까?

분류에서Dev

'.join'함수를 사용하기 위해 목록을 float로 변환하는 방법은 무엇입니까?

분류에서Dev

다른 함수를 호출하기 위해 가변 템플릿 인수를 다른 유형으로 변환하는 방법은 무엇입니까?

분류에서Dev

onnx 변환을 위해 환경 변수 TF_Keras = 1을 설정하는 방법은 무엇입니까?

분류에서Dev

imagemagick 변환을위한 입력 이미지 형식을 정의하는 방법은 무엇입니까?

분류에서Dev

Matlab에서 함수를 호출하기 위해 '시간'을 구현하는 방법은 무엇입니까?

분류에서Dev

SQL을 쿼리하기 위해 변수를 대체하는 방법은 무엇입니까?

분류에서Dev

함수 호출을 반환하는 함수를 문서화하는 방법 (꼬리 호출 최적화를 위해)

분류에서Dev

함수 호출을 위해 토큰 붙여 넣기를 수행하는 방법은 무엇입니까?

분류에서Dev

이 비트 꼬기 패턴을 해결하는 변환은 무엇입니까?

분류에서Dev

특수 문자를 지원하기 위해 VARCHAR 열을 정의하는 방법은 무엇입니까?

분류에서Dev

미리 정의 된 함수를 호출하고 해당 함수 내에있는 변수의 속성에 액세스하는 방법은 무엇입니까?

분류에서Dev

완료 처리기로 UIImageWriteToSavedPhotosAlbum ()을 호출하기 위해 정적 함수를 사용하는 방법은 무엇입니까?

분류에서Dev

Q를 사용하기 위해 Node JS에서 호출하지 않고 함수 호출을 배열로 푸시하는 방법은 무엇입니까?

분류에서Dev

나중에 사용하기 위해 각 반환 값을 변수로 얻는 방법은 무엇입니까?

분류에서Dev

10 진수 값을 얻기 위해 C #에서 44/5를 변환하는 방법은 무엇입니까?

분류에서Dev

10 진수 값을 얻기 위해 C #에서 44/5를 변환하는 방법은 무엇입니까?

분류에서Dev

계산 된 열을 추가하기 위해 dplyr의 R mutate 함수에서 함수를 호출하는 방법은 무엇입니까?

분류에서Dev

계산 된 열을 추가하기 위해 dplyr의 R mutate 함수에서 함수를 호출하는 방법은 무엇입니까?

분류에서Dev

쿼리를 위해 NSString 유형의 여러 값을 함께 전달하는 방법은 무엇입니까?

분류에서Dev

모호한 형변환 / 변환을 처리하는 올바른 방법은 무엇입니까 C ++ 11

분류에서Dev

수량 단위 변환으로 그룹 별 쿼리 SQL을 작성하는 방법은 무엇입니까?

분류에서Dev

변수를 변경하기 위해 메서드를 여러 번 호출하는 방법은 무엇입니까?

분류에서Dev

후속 하위 쿼리에 대한 지역 변수를 선언하기 위해 case 문을 사용하는 방법은 무엇입니까?

분류에서Dev

FMU와 상호 작용하는 동안 단위 변환을 처리하는 방법은 무엇입니까?

분류에서Dev

Java 형식 ddMMyyyyHmmss의 문자열을 Oracle 함수 to_date ()에 의해 날짜로 변환하는 방법은 무엇입니까?

분류에서Dev

jenkins-job-builder를 사용하기 위해 jenkins 작업 구성 config.xml을 Python의 YAML 형식으로 변환하는 방법은 무엇입니까?

분류에서Dev

scipy.stats에서 푸 아송 분포의 꼬리 값을 지정하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    환경 변수로 호출을 하위 처리하는 방법은 무엇입니까?

  2. 2

    useEffect 후크에 의해 호출되는 함수 호출을 중지하기 위해`onClick` 이벤트를 사용하는 방법은 무엇입니까?

  3. 3

    '.join'함수를 사용하기 위해 목록을 float로 변환하는 방법은 무엇입니까?

  4. 4

    다른 함수를 호출하기 위해 가변 템플릿 인수를 다른 유형으로 변환하는 방법은 무엇입니까?

  5. 5

    onnx 변환을 위해 환경 변수 TF_Keras = 1을 설정하는 방법은 무엇입니까?

  6. 6

    imagemagick 변환을위한 입력 이미지 형식을 정의하는 방법은 무엇입니까?

  7. 7

    Matlab에서 함수를 호출하기 위해 '시간'을 구현하는 방법은 무엇입니까?

  8. 8

    SQL을 쿼리하기 위해 변수를 대체하는 방법은 무엇입니까?

  9. 9

    함수 호출을 반환하는 함수를 문서화하는 방법 (꼬리 호출 최적화를 위해)

  10. 10

    함수 호출을 위해 토큰 붙여 넣기를 수행하는 방법은 무엇입니까?

  11. 11

    이 비트 꼬기 패턴을 해결하는 변환은 무엇입니까?

  12. 12

    특수 문자를 지원하기 위해 VARCHAR 열을 정의하는 방법은 무엇입니까?

  13. 13

    미리 정의 된 함수를 호출하고 해당 함수 내에있는 변수의 속성에 액세스하는 방법은 무엇입니까?

  14. 14

    완료 처리기로 UIImageWriteToSavedPhotosAlbum ()을 호출하기 위해 정적 함수를 사용하는 방법은 무엇입니까?

  15. 15

    Q를 사용하기 위해 Node JS에서 호출하지 않고 함수 호출을 배열로 푸시하는 방법은 무엇입니까?

  16. 16

    나중에 사용하기 위해 각 반환 값을 변수로 얻는 방법은 무엇입니까?

  17. 17

    10 진수 값을 얻기 위해 C #에서 44/5를 변환하는 방법은 무엇입니까?

  18. 18

    10 진수 값을 얻기 위해 C #에서 44/5를 변환하는 방법은 무엇입니까?

  19. 19

    계산 된 열을 추가하기 위해 dplyr의 R mutate 함수에서 함수를 호출하는 방법은 무엇입니까?

  20. 20

    계산 된 열을 추가하기 위해 dplyr의 R mutate 함수에서 함수를 호출하는 방법은 무엇입니까?

  21. 21

    쿼리를 위해 NSString 유형의 여러 값을 함께 전달하는 방법은 무엇입니까?

  22. 22

    모호한 형변환 / 변환을 처리하는 올바른 방법은 무엇입니까 C ++ 11

  23. 23

    수량 단위 변환으로 그룹 별 쿼리 SQL을 작성하는 방법은 무엇입니까?

  24. 24

    변수를 변경하기 위해 메서드를 여러 번 호출하는 방법은 무엇입니까?

  25. 25

    후속 하위 쿼리에 대한 지역 변수를 선언하기 위해 case 문을 사용하는 방법은 무엇입니까?

  26. 26

    FMU와 상호 작용하는 동안 단위 변환을 처리하는 방법은 무엇입니까?

  27. 27

    Java 형식 ddMMyyyyHmmss의 문자열을 Oracle 함수 to_date ()에 의해 날짜로 변환하는 방법은 무엇입니까?

  28. 28

    jenkins-job-builder를 사용하기 위해 jenkins 작업 구성 config.xml을 Python의 YAML 형식으로 변환하는 방법은 무엇입니까?

  29. 29

    scipy.stats에서 푸 아송 분포의 꼬리 값을 지정하는 방법은 무엇입니까?

뜨겁다태그

보관