첫째, 목록은 일종의 나무입니다. 리스트를 링크 된 리스트로 나타내면 각 노드에 1 또는 0 자손이 있는 트리 일뿐 입니다.
구문 분석 트리는 데이터 구조로 트리를 활용하는 것입니다. 트리에는 정렬, 맵 구현, 연관 배열 등 컴퓨터 과학에 많은 응용 프로그램이 있습니다.
일반적으로 목록, 트리 등은 재귀 데이터 구조입니다. 각 노드에는 일부 정보와 동일한 데이터 구조의 다른 인스턴스가 있습니다. 폴딩은 노드를 "하단"값으로 재귀 적으로 변환하는 모든 이러한 구조에 대한 작업입니다. 펼치기는 반대 과정으로, 값을 "하향식"노드로 변환합니다.
주어진 데이터 구조에 대해 기계적으로 폴딩 및 언 폴딩 기능을 구성 할 수 있습니다.
예를 들어, 목록을 보자. (입력 된 예제와 구문이 매우 깨끗하므로 Haskell을 사용하겠습니다.) List는 끝이거나 값이며 "꼬리"입니다.
data List a = Nil | Cons a (List a)
이제리스트를 접고 있다고 상상해 봅시다. 각 단계에서 현재 노드를 접고 재귀 하위 노드를 이미 접었습니다. 이 상태를 다음과 같이 나타낼 수 있습니다
data ListF a r = NilF | ConsF a r
여기서 r
하위 목록을 접어 구성한 중간 값입니다. 이를 통해 목록에 대해 접기 기능을 표현할 수 있습니다.
foldList :: (ListF a r -> r) -> List a -> r
foldList f Nil = f NilF
foldList f (Cons x xs) = f (ConsF x (foldList f xs))
우리는 변환 List
에 ListF
재귀의 하위 목록을 통해 접어서 다음에 정의 된 함수를 사용합니다 ListF
. 당신이 그것에 대해 생각하면, 이것은 표준의 또 다른 표현 일뿐입니다 foldr
.
foldr :: (a -> r -> r) -> r -> List a -> r
foldr f z = foldList g
where
g NilF = z
g (ConsF x r) = f x r
우리는 unfoldList
같은 방식으로 구성 할 수 있습니다 .
unfoldList :: (r -> ListF a r) -> r -> List a
unfoldList f r = case f r of
NilF -> Nil
ConsF x r' -> Cons x (unfoldList f r')
다시 말하지만, 이것은 또 다른 표현입니다 unfoldr
.
unfoldr :: (r -> Maybe (a, r)) -> r -> [a]
(의 Maybe (a, r)
동형 ListF a r
입니다.)
삼림 벌채 기능도 구성 할 수 있습니다.
deforest :: (ListF a r -> r) -> (s -> ListF a s) -> s -> r
deforest f u s = f (map (deforest f u) (u s))
where
map h NilF = NilF
map h (ConsF x r) = ConsF x (h r)
단순히 중간체를 빼고 List
접는 기능과 접는 기능을 융합합니다.
모든 재귀 데이터 구조에 동일한 절차를 적용 할 수 있습니다. 예를 들어, 노드에 0, 1, 2 또는 1 또는 0 분기 노드에 값이있는 자손이있는 트리는 다음과 같습니다.
data Tree a = Bin (Tree a) (Tree a) | Un a (Tree a) | Leaf a
data TreeF a r = BinF r r | UnF a r | LeafF a
treeFold :: (TreeF a r -> r) -> Tree a -> r
treeFold f (Leaf x) = f (LeafF x)
treeFold f (Un x r) = f (UnF x (treeFold f r))
treeFold f (Bin r1 r2) = f (BinF (treeFold f r1) (treeFold f r2))
treeUnfold :: (r -> TreeF a r) -> r -> Tree a
treeUnfold f r = case f r of
LeafF x -> Leaf x
UnF x r -> Un x (treeUnfold f r)
BinF r1 r2 -> Bin (treeUnfold f r1) (treeUnfold f r2)
물론 deforestTree
이전과 마찬가지로 기계적으로 만들 수 있습니다 .
일반적 treeFold
으로 다음과 같이 더 편리하게 표현 합니다.
treeFold' :: (r -> r -> r) -> (a -> r -> r) -> (a -> r) -> Tree a -> r
)
세부 사항을 생략하고 패턴이 분명하기를 바랍니다.
또한보십시오: