이것은 "Compute an (infinite) tree from fixpoint operator using delay modality"의 변형입니다.지연 모달을 사용하여 루트 경로에서 무한 트리를 계산하십시오.
설정입니다.
type Path = [Bool]
data STree = SNode STree STree
| SPath Path
| SLeaf Int
deriving (Show)
경로가 어떤 루트의 맥락에서 정의되며,이 식별 : 우리는 루트에서 경로 트리의 임의의 다른 노드를 참조 할 수있는 능력 증강 이진 트리의 언어를 공부 경로에서 거짓/참을 볼 때 왼쪽/오른쪽 자식을 따라 연속적으로 발견 된 하위 트리. 예를 들어 경로 [False, True]
은 SNode (SNode (SLeaf 1) (SLeaf 2)) (SLeaf 3)
트리의 SLeaf 2
을 식별합니다.
이러한 나무는 임의의 흐름 그래프를 식별하는데 이용 될 수있다 (돌이킬 수없는 그래프, fixpoint 연산자를 사용 할 수 없습니다 것을 포함합니다.)
우리는이 설명에 의해 유도 된 무한 트리를 고려할 수 있습니다. 여기
data Tree = Node Tree Tree
| Leaf Int
deriving (Show)
이 나무의 일부 경로에 서브 트리를 발견 보조 기능
follow
사용하는 다른 하나에서 변환 함수입니다 : 불행하게도
follow :: Path -> Tree -> Tree
follow [] s = s
follow (False : p) (Node s _) = follow p s
follow (True : p) (Node _ s) = follow p s
follow _ (Leaf _) = error "bad path"
flatten' :: Tree -> STree -> Tree
flatten' root (SPath p) = follow p root
flatten' root (SNode s1 s2) =
Node (flatten' root s1) (flatten' root s2)
flatten' _ (SLeaf i) = Leaf i
flatten :: STree -> Tree
flatten s = fix (\root -> flatten' root s)
을,이 기능은 생산되지 않습니다 : 그것은 무한 루프가 flatten (SPath [])
에 있습니다.
문제가 있습니다. 이제 우리는 지연 모달리티 ("Compute an (infinite) tree from fixpoint operator using delay modality"에서 설명 됨)와 함께 Loop
생성자를 사용하여 자체 참조 루프를 나타 내기 위해이 구조의 변형을 고려합니다.
data Tree = Node (D Tree) (D Tree)
| Leaf Int
| Loop
deriving (Show)
비 구조적으로 재귀 함수 호출을 사용하지 않고 (그래서, 당신은 구조적으로 같이 Recurse STree
및 Path
에 수), 무한 트리를 전개하는 기능 STree -> Tree
(또는 유사)를 작성합니다.
추록. 많은 경우, 우리는 무한 전개를 계산하기를 원하지 않습니다. 존재하는 경우 유한 전개를 원하고, 그렇지 않으면 오류를 원합니다. 특히, 원래 데이터 형식 주어진 : 비 구조적으로 재귀 사용하지 않고
data Tree = Node Tree Tree
| Leaf Int
deriving (Show)
을, 우리는 그것이 존재하는 경우 유한 트리로 구문을 전개하고, 그렇지 않으면 실패하는 기능 STree -> Maybe Tree
(또는 유사)을 작성 할 수 있습니다. 이 구조에서 지연 양식이 없기 때문에이 구조가 유한 함을 보증합니다.
이 구조에는 지연 양식이 없기 때문에 fixD
을 사용하면 불가능합니다. 우리는 결코 사용할 수없는 지연된 결과를 얻게됩니다. 우리는 트리를 그래프로 변환하고 토폴로지별로 정렬 한 다음 fixD
을 사용하지 않고 알고리즘을 직접 구현하는 것으로 보입니다.
언 폴딩을 원래의 (잘못된) 코드처럼 우아하게 구현할 수있는 다른 타이핑 규율이 있습니까? 그렇다면 그래프에서주기를 찾는 또 다른 알고리즘을 (재) 발견했을 수 있습니다.
'flatten (SPath [])'에서 수행 할 수있는 것은 없지만 무한 루프 (또는 다른 하단 값 반환)입니다. 거기에 해당 할 수있는'Tree '가 없습니다. 두 번째 예제에서는 'Loop'일 수 있지만 루프 감지가 필요합니다. 트리에서 참조를 명시 적으로 나타낼 수 있어야합니다 (알려진 생성자를 가짐). 또는 어떤 생성자가 경로가 선험적으로 갈지를 알아야합니다. – Cirdec
글쎄, '루프'를 사용하는 종료 기능을 작성하는 것은 그리 어렵지 않지만 루프 감지가 필요하다고 말한 것처럼 말입니다. 이 기능의 생산성이 명백하게 명백해질 수 있습니까? 그게 질문입니다! (이전의 경우에는 루프를 쉽게 찾을 수있는 방법이 있었음을 지적 할 것입니다. –