코어커시온

Corecursion

컴퓨터 과학에서 코어커션재귀이중인 수술의 일종이다. 재귀는 기초 사례에서 더 멀리 떨어진 데이터에서 시작하여 더 작은 데이터로 분해하여 기초 사례에 도달할 때까지 반복하는 분석적으로 작용하는 반면, 코어커서는 기초 사례에서 시작하여 기초 사례에서 더 이상 제거된 데이터를 반복적으로 생성한다. 간단히 말해서, 코어커서 알고리즘은 그 자체로 생산되는 데이터를 조금씩 조금씩 더 많은 데이터를 생산하기 위해 사용한다. 유사하지만 뚜렷한 개념은 생성적 재귀인데, 이는 핵심구간과 재귀에 내재된 확실한 "방향"이 결여될 수 있다.

재귀로 프로그램이 임의적으로 복잡한 데이터에서 작동할 수 있는 경우, 프로그램이 단순한 데이터(기본 사례)로 축소될 수 있는 한(기본 사례) 코어커서는 프로그램이 연속적인 유한 단계에서의 단순 데이터(기본 사례)에서 생성될 수 있는 한, 스트림과 같이 임의적으로 복잡하고 잠재적으로 무한할 수 있는 데이터 구조를 만들 수 있다. 재귀가 종료되지 않을 수 있고, 절대 기준 상태에 도달하지 않을 수 있으며, 핵심구조는 기준 상태에서 시작되며, 따라서 결정적으로 후속 단계를 생성하지만(그래서 엄격한 평가 하에서 종료되지 않을 수도 있음), 또는 그것이 생산하는 것보다 더 많이 소비하여 비생산적이 될 수도 있다. 전통적으로 재귀적으로 분석되는 많은 기능들은 대안으로, 그리고 논쟁의 여지가 더 없이 자연적으로, 예를 들어 요인 같은 재발 관계와 같은 주어진 단계에서 종료되는 코어커서 함수로 해석될 수 있다.

코어커서는 유한데이터 구조와 무한 데이터 구조를 모두 결과로서 생성할 수 있으며, 자체 재주 데이터 구조를 채택할 수 있다. 코어커서는 종종 게으른 평가와 함께 사용되는데, 잠재적으로 무한할 수 있는 구조의 유한 부분 집합만을 생산하기 위해(한 번에 전체 무한 구조를 생산하려고 하는 것이 아니라) 사용된다. 코어커서는 기능 프로그래밍에서 특히 중요한 개념으로, 코커서와 코다타는언어가 무한한 데이터 구조로 작동할 수 있도록 한다.

코어커서는 재귀와는 대조적으로 이해할 수 있는데, 이는 더욱 친숙한 것이다. 코어커서는 주로 기능 프로그래밍에 관심이 있지만, 아래 파이썬의 제너레이터 설비를 사용하여 수행되는 명령 프로그래밍을 사용하여 설명할 수 있다. 이러한 예에서 지역 변수를 사용하고 (파괴적으로) 반드시 값을 할당하지만, 이러한 변수는 순수한 기능 프로그래밍에서 코어커서에 필요하지 않다. 순수 기능 프로그래밍에서, 로컬 변수에 할당하기 보다는, 이러한 계산된 값은 불변의 시퀀스를 형성하며, 사전 값은 자가 참조에 의해 접근된다(순서의 더 느린 값은 계산할 시퀀스의 이전 값을 참조한다). 과제들은 이것을 명령적 패러다임에서 간단히 표현하고 어디에서 계산이 일어나는지 명시적으로 명시하는 것으로, 이것이 전시를 명확히 하는 역할을 한다.

요인

재귀의 전형적인 예로는 0! := 1n! :=n × (n - 1)로 재귀적으로 정의되는 요인 계산이 있다.

주어진 입력에 대한 결과를 재귀적으로 계산하기 위해, 재귀 함수는 다른 ("어떤 면에서 더 작은") 입력으로 스스로 호출하고 이 호출의 결과를 그 결과를 구성하기 위해 사용한다. 재귀 호출은 기본 사례에 도달하지 않는 한 동일하게 한다. 따라서 그 과정에서 콜 스택이 발생한다. 예를 들어, fac(3)를 계산하기 위해, 이것은 반복적으로 fac(2), fac(1), fac(0)(0) = 1로 재귀가 종료되는 시점("스택을 위로")에서 스택이 역순으로 풀리고 결과는 fac(2) = 2 - c의 결과를 사용하는 초기 호출 프레임 fac(3)으로 돌아오는 길에 계산된다.최종 결과를 3 × 2 = 3 × fac(2) =: fac(3)로 표시하고 최종적으로 fac(3) = 6. 이 예에서 함수는 단일 값을 반환한다.

스택 풀림은 1 의 사례로 시작하여시작 값에서 1, 2, 3을 증가시키기 위한 요인 값을 생성하며, 위의 재귀적 정의에서처럼 "시간 화살표"를 거꾸로 읽음으로써 설명할 수 있다. n !( + 1) (+ )! )!}. 따라서 정의된 코어커서 알고리즘은 모든 요인의 스트림을 생성한다. 이것은 발전기로서 구체적으로 구현될 수 있다. 상징적으로 다음 요인 값을 계산하려면 nf(이전의 요인 값)를 모두 추적해야 한다는 점에 주목하면, 이는 다음과 같이 나타낼 수 있다.

아니면 하스켈에서

  (\(n,f) -> (n+1, f*(n+1))) `반복하다` (0,1) 

의미, ", = 0,로부터 시작하여각 단계에서 다음 값은 + 1, (n + ,("로 계산한다. 이는 수학적으로 동일하고 재귀적 정의와 거의 동일하지만 + {\은 요인 값이 처음 뒤로 이동한 후 계산되는 것이 아니라 시작 사례에서 앞으로 전진하여- 1 감소를 통해 생성되고 있음을 강조한다. 코어커서함수의 직접 출력은 단순히 n! 값을 포함하는 것이 아니라, 각 값에 대한 지수 n의 보조 데이터를 시퀀스에 포함시켜, 필요에 따라 이들 중에서 하나의 특정 결과를 모두 선택할 수 있다.

이러한 방식으로 재귀적 프로그램의 변조가 핵심적으로 구축되는 변절적 의미론과의 연관성이 있다.

Python에서 재귀 요인 함수는 다음과 같이 정의할 수 있다.[a]

반항하다 요인의(n):     """재발 요인 함수."""     만일 n == 0:         돌아오다 1     다른:         돌아오다 n * 요인의(n - 1) 

이것은 예를 들면 다음과 같이 불릴 수 있다. factorial(5) 5를 계산하기 위해서!

해당 코어커서 발전기는 다음과 같이 정의할 수 있다.

반항하다 요인():     """핵심 발전기."""     n, f = 0, 1     하는 동안에 진실의:         양보하다 f         n, f = n + 1, f * (n + 1) 

이것은 순서에 따라 무한히 많은 요인 흐름을 생성하며, 그 중 유한한 부분은 다음과 같은 방법으로 생성될 수 있다.

반항하다 n_vms(k):     n, f = 0, 1     하는 동안에 n <= k:         양보하다 f         n, f = n + 1, f * (n + 1) 

그 후 다음을 통해 최대 5!까지의 요인을 생성하기 위해 이를 호출할 수 있다.

을 위해 f  n_vms(5):     인쇄하다(f) 

특정 요인에만 관심이 있다면 마지막 값만 취하거나 생산과 액세스를 하나의 함수에 융합할 수 있다면

반항하다 nth_message(k):     n, f = 0, 1     하는 동안에 n < k:         n, f = n + 1, f * (n + 1)     양보하다 f 

여기서 쉽게 알 수 있듯이, 이것은 (대용하는 것만으로) 실질적으로 동등하다. return 단 한 사람으로서 yield 거기서) 꼬리 재귀에 대한 축전지의 논거 기법에 대해 명시적 루프로 분해한다. 따라서 코어커시온의 개념은 해당되는 경우 재귀적 정의에 의한 반복적 계산 프로세스의 구현을 탐구하는 것이라고 말할 수 있다.

피보나치 수열

같은 방법으로 피보나치 수열은 다음과 같이 나타낼 수 있다.

피보나치 수열은 순서 2의 반복 관계이므로, 핵심관계는 한 단계씩 전진하는 것에 해당하는 ,-) 과 다음 용어 계산에 해당하는(-, + b){\을 가진 연속적인 두 항을 추적해야 한다. 그런 다음 다음과 같이 구현할 수 있다(병렬 할당 사용):

반항하다 fibonacci_properties():     a, b = 0, 1     하는 동안에 진실의:         양보하다 a         a, b = b, a + b 

하스켈에서는

 지도를 그리다 fst ( (\(a,b) -> (b,a+b)) `반복하다` (0,1) ) 

나무횡단

깊이 우선 접근법을 통한 나무 횡단은 재귀의 전형적인 예다. 한 달에 한 번, 너비 우선 통과는 코어커서를 통해 매우 자연스럽게 구현될 수 있다.

특별히 재귀 또는 코어커서를 사용하지 않고 루트 노드에서 시작하여 하위 노드를 데이터 구조로 배치한 다음, 제거된 각 노드의 하위 노드를 데이터 구조로 다시 배치하면서 데이터 구조에서 노드 후 노드를 제거하여 반복함으로써 트리를 통과할 수 있다.[b] 데이터 구조가 스택(LIFO)이면 깊이 우선의 통과를, 데이터 구조가 대기열(FIFO)이면 너비 우선 통과를 산출한다.

재귀법을 사용하여 (주문 후)[c] 깊이-최초의 트래버설을 루트 노드에서 시작하여 각 하위 하위 트리를 차례로 재귀적으로 트래버싱(각 하위 노드에 기초한 하위 트리)하여 실행할 수 있다. - 두 번째 하위 하위 하위 트리는 첫 번째 하위 하위 트리가 완료될 때까지 처리를 시작하지 않는다. 리프 노드에 도달하거나 분기 노드의 하위 노드가 소진되면 노드 자체를 방문한다(예: 노드 자체의 값이 출력된다). 이 경우, (재귀 함수의) 콜 스택은 반복된 스택의 역할을 한다.

corecursion 이용해breadth-first의 횡단 루트 노드에에서 시작하여, 즉 subtrees –를 누비며 breadth-first, subtrees의 전체 목록 다음 단계로 – 다음 단계는 모든 뿌리 노드 뒤의 값을 출력하기에(반복적인 접근에 없기 때문에 하위 트리,) 지나가는 그 value,[d]을 출력하기 구현할 수 있다.파파자녀에게 sing on the child subtree [e] 이 경우, 실제로 출력 시퀀스 자체인 제너레이터 기능이 대기열 역할을 한다. 요인 예제(위)에서와 같이, 지수의 보조 정보(1단계는 n!의 실제 출력에 더하여, n)를 추진한 경우, 이 경우 나머지 하위 트리의 보조 정보는 실제 출력에 더하여 앞으로 추진된다. 상징적으로:

각 단계에서 루트 노드의 값 목록을 출력한 다음 하위 하위 트리로 진행한다는 의미. 이 시퀀스에서 노드 값만 생성하면 보조 하위 트리 데이터를 삭제한 다음 목록(이 값은 처음에 수준(깊이)별로 그룹화됨; 평탄화(그룹화 해제)하면 평탄한 선형 목록이 나온다. 하스켈에서는

 콘카트맵 fst ( (\(v, t) -> (루트값 v t, 차일드 트리스 t)) `반복하다` ([], 풀트리) ) 

이것들을 다음과 같이 비교할 수 있다. 재귀적 횡단은 (하단의) 잎 노드(하단의)를 베이스 케이스로 처리하고, 트리를 하위 트리로 분석하여 각 노드(자녀가 없을 때는 값을 출력하기만 함)를 차례로 가로지르며, 결국 단지 잎 노드(실제 리프 노드)와 이미 자식을 처리한 가지 노드(아래 잘라짐)를 낳는다. 이와는 대조적으로, 코어 통과는 기본 케이스로서 루트 노드(상단의 노드)를 처리하고(노드가 주어진 경우, 먼저 값을 출력하고), 트리를 루트 노드와 그 하위 노드의 합성된 것으로 처리한 후, 각 단계의 하위 트리 목록을 보조 출력으로 생산하고, 다음 단계의 입력값인 다음, 원래의 루트의 하위 노드는 다음과 같다. 다음 단계의 루트 노드(의 컷오프)는 부모가 이미 처리된 상태임. 재귀적 횡단에서는 리프 노드와 분기 노드의 구분이 있는 반면, 코어커서 횡단에서는 각 노드가 그것이 정의하는 하위 트리의 루트 노드로 취급되기 때문에 구분이 없다.

반면, 재귀적 depth-first의 횡단이 나뭇가지와 모든 노드를 횡단하지 않고, 만약 사활강 post-order기 때문에 a지, 이 예에(또는in-order)이것이 그저, 노드를 방문할 것이다 특히 무한은corecursive breadth-first 가로지르는 모든 노드를 가로지를 거 tree,[f], 단지 유한한 나무는 주어진르이것은 무한 데이터 구조를 다루기 위한 재귀보다 코어커서의 유용성을 보여준다.

파이톤에서는 이것을 다음과 같이 구현할 수 있다.[g] 통상적인 주문 후 깊이 첫 번째 통과는 다음과 같이 정의할 수 있다.[h]

반항하다 df(마디를 짓다):     """"주문 후 깊이-첫 번째 통과."""     만일 마디를 짓다 이다 아닌 없음:         df(마디를 짓다.남겨진)         df(마디를 짓다.맞다)         인쇄하다(마디를 짓다.가치를 매기다) 

이것은 다음으로 호출될 수 있다. df(t) 트리의 노드 값을 주문 후 깊이 우선 순서에 따라 인쇄한다.

폭 첫 번째 코어커서 발전기는 다음과 같이 정의할 수 있다.[i]

반항하다 bf(나무):     """"Breadth-first corecursive generator."""     tree_list = [나무]     하는 동안에 tree_list:         new_tree_list = []         을 위해 나무  tree_list:             만일 나무 이다 아닌 없음:                 양보하다 나무.가치를 매기다                 new_tree_list.덧셈을(나무.남겨진)                 new_tree_list.덧셈을(나무.맞다)         tree_list = new_tree_list 

그런 다음, 트리의 노드 값을 너비 우선 순서에 따라 인쇄하기 위해 호출할 수 있다.

을 위해 i  bf(t):     인쇄하다(i) 

정의

초기 데이터 형식은 일부 형식 방정식의 최소 고정점(이형성까지의)으로 정의할 수 있다. 이형성초기 대수학에 의해 주어진다. 한 번에 최종(또는 단자) 데이터 유형은 유형 방정식의 가장 큰 고정점으로 정의될 수 있다. 이형성은 최종 결합형에 의해 주어진다.

담화 영역이 집합과 총함수의 범주인 경우, 최종 데이터 형식은 무한하고 근거 없는 값을 포함할 수 있지만 초기 형식은 그렇지 않다.[1][2] 한편 담론의 영역이 하스켈 프로그래밍 언어에 대략 해당하는 완전한 부분순서연속함수의 범주라면, 최종유형은 초기유형과 일치하며, 그에 상응하는 최종합금형과 초기대수는 이형성을 형성한다.[3]

코어커서는 일반 재귀가 초기 데이터 유형인 함수를 재귀적으로 정의하는 방식과 이중으로, 범위(코도메인)가 최종 데이터 유형인 함수를 재귀적으로 정의하는 기법이다.[4]

아래 논의는 하스켈에서 핵심을 구별하는 몇 가지 예를 제공한다. 대략적으로 말해서, 만약 이 정의들을 집합의 범주에 배치한다면, 그것들은 여전히 핵심적일 것이다. 이 비공식적인 용법은 하스켈에 관한 기존의 교과서와 일치한다.[5] 이 글에서 사용된 예는 핵심을 정의하고 그것이 무엇인지 설명하려는 시도보다 앞서 있다.

토론

코다타에 대한 원시적 중심부의 규칙은 데이터에 대한 원시적 재귀에 대한 규칙과 이중적이다. 그 생성자에 대한 패턴 매칭으로 논쟁에 착수하는 것이 아니라(이전에 어디선가 불러올있기 때문에 우리는 이미 만들어진 기준점을 받고 그 구성 요소인 "현장"에 도달한다), 우리는 그 "파괴자" (또는 "파괴자")를 채움으로써 그 결과에 도달하고, 그 후에 어딘가로 불리게 될 "파괴자" (또는 "파괴자")를 채움으로써 실제로 우리는 그 결과를 부르고 있다. 생성자, 나중에 관찰할 결과의 다른 비트를 생성). 따라서 코어커서는 (잠재적으로 무한한) 코다타를 생성하는 반면, 일반 재귀 분석(필요하게 유한한) 데이터는 생성된다. 일반 재귀는 종료되지 않을 수 있으므로 코다타에 적용되지 않을 수 있다. 반대로, 데이터가 유한해야 하기 때문에 결과 유형이 데이터인 경우에는 핵심이 엄격히 필요하지 않다.

"Coq의 하천 프로그래밍: 사례 연구: Eratosthenes의 체"[6]에서 찾을 수 있다.

hd (콩쿠르를 붙이다 a s) = a                tl (콩쿠르를 붙이다 a s) = s  (체에 밭다 p s) = 만일 칸막이하다 p (hd s) 그때 체에 밭다 p (tl s)               다른 콩쿠르를 붙이다 (hd s) (체에 밭다 p (tl s))  hd (프라임즈 s) = (hd s)           tl (프라임즈 s) = 프라임즈 (체에 밭다 (hd s) (tl s)) 

여기서 primes "reimes 연산(Enu 2)을 스트림에 적용하여 primes"를 얻는다. 위의 표기법에 따라 소수점(버리기 0이 앞에 붙음)의 순서와 숫자 스트림이 점진적으로 체인지되는 것을 다음과 같이 나타낼 수 있다.

아니면 하스켈에서

(\(p, s@(h:t)) -> (h, 체에 밭다 h t)) `반복하다` (0, [2..]) 

저자들은 어떻게 정의가 sieve 항상 생산성이 보장되지 않으며, 예를 들어, 다음과 같이 호출될 경우 고착될 수 있다. [5,10..] 시류로

여기 하스켈의 또 다른 예가 있다. 다음 정의는 피보나치 숫자의 목록을 선형 시간으로 생성한다.

섬유질 = 0 : 1 : zipWith (+) 섬유질 (꼬리를 치다 섬유질) 

이 무한한 목록은 게으른 평가에 달려있다; 요소들은 필요에 따라 계산되고 오직 한정된 접두사만이 기억 속에 명시적으로 표현된다. 이 기능은 코다타 부분의 알고리즘을 종료할 수 있게 한다. 그러한 기술은 하스켈 프로그래밍의 중요한 부분이다.

Python에서도 이 작업을 수행할 수 있음:[7]

로부터 이터툴스 수입하다 티를 내다, 쇠사슬을 매다, 이슬라이스, 잽싸게 하다  반항하다 덧셈을(x, y):     돌아오다 x + y  반항하다 피보나치():     반항하다 이연_출력():         을 위해 i  생산량:             양보하다 i     결과, c1, c2 = 티를 내다(이연_출력(), 3)     짝을 이룬 = 잽싸게 하다(덧셈을, c1, 이슬라이스(c2, 1, 없음))     생산량 = 쇠사슬을 매다([0, 1], 짝을 이룬)     돌아오다 결과  을 위해 i  이슬라이스(피보나치(), 20):     인쇄하다(i) 

의 정의 zipWith 인라인 방식으로 다음을 수행할 수 있음:

섬유질 = 0 : 1 : 다음에 섬유질   어디에     다음에 (a: t@(b:_)) = (a+b):다음에 t 

이 예에서는 자기 주도 데이터 구조를 사용한다. 일반적인 재귀는 자기주변 함수를 사용하지만 자기주변 데이터는 수용하지 않는다. 그러나, 이것은 피보나찌의 예에 필수적인 것은 아니다. 다음과 같이 다시 쓸 수 있다.

섬유질 = 섬유질 (0,1) 섬유질 (x,y) = x : 섬유질 (y,x+y) 

이것은 결과를 구성하기 위해 자기주조 기능만 사용한다. 엄격한 목록 작성자와 함께 사용된다면 그것은 가출 재귀의 예가 될 수 있지만 엄격하지 않은 목록 작성자와 함께 이 보호되는 재귀는 점차적으로 무한정 정의된 목록을 생성한다.

코어커서는 무한한 물체를 만들 필요가 없다; 코커서 큐는 특히[8] 이 현상의 좋은 예다. 다음 정의는 선형 시간 내에 이진 트리의 너비 우선 통과를 생성한다.

자료 나무 a b =  a     나뭇가지 b (나무 a b) (나무 a b)  격자무늬의 :: 나무 a b -> [나무 a b] 격자무늬의 나무 = 줄을 서다   어디에     줄을 서다 = 나무 :  1 줄을 서다        0   p                 =         []                  (   _     : s) =          (-1) s        (나뭇가지 _ l r : s) = l : r :  (+1) s 

이 정의는 초기 트리를 취하고 하위 트리 목록을 생성한다. 이 목록은 대기열과 결과 둘 다로서 이중의 목적을 제공한다(gen len p 를 따라 입력 백 포인터를 지나 출력 노치가 생성됨). 초기 트리가 유한한 경우에만 유한하다. 종료를 보장하기 위해 대기열의 길이를 명시적으로 추적해야 한다. 이 정의가 무한대 나무에만 적용되는 경우 안전하게 적용할 수 있다.

또 다른 특히 좋은 예는 너비 우선 라벨링 문제에 대한 해결책을 제시한다.[9] 함수 label 2진수 트리의 모든 노드를 첫 번째 방식으로 방문하며, 각 레이블을 정수로 대체하며, 각각의 후속 정수는 마지막 정수보다 하나씩 더 크다. 이 솔루션은 자기주요 데이터 구조를 채용하며, 이진 트리는 유한하거나 무한할 수 있다.

라벨을 붙이다 :: 나무 a b -> 나무 인트 인트  라벨을 붙이다 t = t     어디에     (t, ns) = 가다 t (1:ns)      가다 :: 나무 a b    -> [인트]  -> (나무 인트 인트, [인트])     가다   (   _    ) (n:ns) = (   n       , n+1 : ns  )     가다   (나뭇가지 _ l r) (n:ns) = (나뭇가지 n l r , n+1 : ns′′)                                 어디에                                   (l, ns ) = 가다 l ns                                   (r, ns′′) = 가다 r ns 

아포모르피즘(expect무아모르피즘)은 파라모피즘(폴드카타모르피즘)이 재귀의 한 형태인 것과 같은 방식의 코어커시즘의 일종이다.

Coq 인증 보조자는 CoFixpoint 명령을 사용하여 코어 커서와 코인 전도를 지원한다.

역사

순환 프로그래밍이라고 불리는 코어커시온은 적어도휴즈필립 와들러를 학점으로 삼는 (버드 1984년)에게 날짜가 잡힌다; 더 일반적인 형태는 (앨리슨 1989년) 로 개발되었다: 목표가 ( 원래의 동기에는 보다 효율적인 알고리즘 생성(일부 경우 다중 패스를 요구하는 대신 1회 데이터 통과 허용)과 기능 언어로 이중 연계된 목록 및 대기열과 같은 고전적 데이터 구조를 구현하는 것이 포함되었다.

참고 항목

메모들

  1. ^ 입력 데이터의 유효성을 검사하지 않는 중.
  2. ^ 보다 우아하게, 루트 노드 자체를 데이터 구조에 배치한 다음 프로세스를 시작하는 것으로 시작할 수 있다.
  3. ^ 사후 주문은 박람회를 위해 "리프 노드는 기본 케이스"를 명시적으로 만드는 것이지만, 사전 주문이나 주문 내에서도 동일한 분석이 가능하다.
  4. ^ 폭 우선횡단은 깊이 우선과 달리 모호하지 않으며, 어린이를 처리하기 전에 노드 값을 방문한다.
  5. ^ 기술적으로, 먼저 각 나무의 루트 노드, 그 다음 각 나무의 자녀, 그 다음 손자녀 등 순서가 정해진 분리되지 않은 나무 세트에 폭 먼저 횡단하는 것을 정의할 수 있다.
  6. ^ 고정 분기 요인(예: 이항) 또는 최소한 경계 및 균형(모든 방향에서 무한)을 가정하십시오.
  7. ^ 먼저 트리 클래스를 정의하고 다음을 수행하십시오.
    계급 나무:     반항하다 __init___(자아의, 가치를 매기다, 남겨진=없음, 맞다=없음):         자아의.가치를 매기다 = 가치를 매기다         자아의.남겨진  = 남겨진         자아의.맞다 = 맞다      반항하다 __str___(자아의):         돌아오다 발을 동동 구르다(자아의.가치를 매기다) 

    트리 초기화는 다음과 같이 하십시오.

    t = 나무(1, 나무(2, 나무(4), 나무(5)), 나무(3, 나무(6), 나무(7))) 

    이 예에서 노드는 너비 우선 순서에 따라 라벨이 지정된다.

        1  2     3 4 5   6 7 
  8. ^ 직관적으로, 함수는 하위 트리에 반복된다(아마도 비어 있을 것이다), 그리고 이것이 끝나면, 남은 것은 노드 자체일 뿐이다. 노드 그 자체가 그 값을 반환한다. 이것은 리프 노드를 기본으로 취급하는 것과 일치한다.
  9. ^ 여기서 인수(및 루프 변수)는 잠재적 리프 노드가 아닌 루트 노드(트리 = 루트 노드)로 표현되는 전체 가능한 무한 트리로 간주되므로 변수 이름을 선택할 수 있다.

참조

  1. ^ 바와이즈와 모스 1996.
  2. ^ 모스와 댄너 1997.
  3. ^ 스미스와 플롯킨 1982.
  4. ^ 기븐스와 허튼 2005년.
  5. ^ Doets and van Eijck 2004. 도트 반 아이크 2004
  6. ^ 르클레르와 폴린 모링, 1994
  7. ^ 헤팅거 2009.
  8. ^ 앨리슨 1989; 스미스 2009.
  9. ^ 존스와 기븐스는 1992년.