변경할 수없는 데이터가있는 언어로 이중 연결 또는 순환 데이터 구조에 대한 작업을 구현하기위한 해결 방법


11

Haskell에서 그래프를 만들고 일부 로컬 작업을 수행하는 방법을 배우고 싶지만 Haskell에만 국한된 문제는 아니며 그래프 대신 이중 연결 목록을 고려할 수 있습니다.

질문 : 이중 연결 목록 (또는 다른 이중 연결 또는 순환 데이터 구조)과 불변 데이터 구조 (Haskell, Clojure 등)를 주로지지하고 옹호하는 언어로 작업을 수행하는 관용적이거나 권장되는 방법은 무엇입니까 ? ? 특히 언어에서 공식적으로 금지하는 전체 업데이트를 사용하는 방법은 무엇입니까?

예를 들어 항목이 삽입 된 경우와 같이 이중 연결 목록에서 일부 로컬 작업을 수행하는 경우 언어의 게으름으로 인해 전체 목록을 즉시 복사 할 필요가 없을 수 있습니다. 그러나 목록이 이중으로 연결되어 있기 때문에 한 곳에서 수정하면 새 버전의 목록에서 이전 노드를 사용할 수 없으며 조만간 표시, 복사, 가비지 수집이 필요합니다. . 업데이트 된 목록의 복사본 만 사용해야하는 경우에는 중복 작업이지만 목록의 크기에 비례하여 "오버 헤드"가 추가됩니다.

이것은 그러한 작업에 대해 불변 데이터가 단순히 부적절하고, 가변 데이터에 대한 "네이티브"지원이없는 기능적 선언적 언어가 명령형 언어만큼 좋지 않다는 것을 의미합니까? 아니면 까다로운 해결 방법이 있습니까?

추신 : 나는이 주제에 관한 기사와 프리젠 테이션을 인터넷에서 찾았지만 그 뒤를 따라가는 데 어려움을 겪었지만이 질문에 대한 답은 한 단락 이상이 아닌 다이어그램을 취해서는 안된다고 생각합니다 ... 이 문제에 대한 "기능적"솔루션이 없다면 아마도 "use C"일 것입니다. 하나가 있다면 얼마나 복잡 할 수 있습니까?


관련 질문


관련 인용

순전히 기능적인 프로그래밍 언어를 사용하면 많은 알고리즘을 매우 간결하게 표현할 수 있지만 업데이트 가능한 상태가 중요한 역할을하는 알고리즘이 몇 가지 있습니다. 이러한 알고리즘의 경우 업데이트 가능한 상태가없는 순수한 기능 언어는 본질적으로 비효율적 인 것으로 보입니다 ( [Ponder, McGeer and Ng, 1988] ).

-John Launchbury 및 Simon Peyton Jones, Lazy 기능 상태 스레드 (1994), John Launchbury 및 Simon Peyton Jones, Haskell 주 (1995). 이 논문 ST은 하스켈에서 모나 딕 타입 생성자를 소개 합니다.



2
참조 주셔서 감사합니다. 그의 논문을 찾았 습니다 .
Alexey

이 논문은 유망한 것으로 보인다 : David King과 John Launchbury의 Haskell (1994)의 Lazy depth-first search 및 선형 그래프 알고리즘 .
Alexey

배열과 비슷한 문제는 유형 을 구현 하는 diffarray 패키지 로 해결됩니다 DiffArray. diffarray 패키지 의 소스 를 보면 91 번의 발생을 볼 수 unsafePerformIO있습니다. 내 질문에 대한 대답은 "예, 아니요, 불변의 데이터를 가진 순전히 기능적인 언어는 일반적으로 전체 업데이트에 의존하는 알고리즘을 구현하는 데 적합하지 않습니다"입니다.
Alexey

(하스켈) 내 현재의 솔루션은 사전을 (사용하는 것입니다 Map, IntMap또는 HashMap스토리지로)와 노드가 링크 노드의 ID를 포함 할 수 있습니다. "컴퓨터 과학의 모든 문제는 다른 수준의 간접 지시로 해결할 수 있습니다."
Alexey

답변:


6

특정 작업에 적합한 다른 효율적인 불변 데이터 구조가있을 수 있지만 이중 연결 목록만큼 일반적이지는 않습니다 (불변 으로 인해 동시 수정 버그가 발생하기 쉽습니다 ). 문제를 더 좁게 지정하면 그러한 구조를 찾을 수 있습니다.

불변 구조의 (상대적으로) 경제 이동에 대한 일반적인 대답은 렌즈입니다. 아이디어는 수정되지 않은 부분과 현재 수정 된 부분에서 수정 된 불변 구조를 재구성하고 인접한 노드로 탐색하기에 충분한 정보 만 유지할 수 있다는 것입니다.

또 다른 유용한 구조는 지퍼 입니다. (재미있는 부분은 렌즈 지퍼의 타입 시그니처가 구조물의 타입 시그니처의 학교 수학 파생물이라는 것입니다.)

다음은 몇 가지 링크입니다.


1
필요한 것이 무엇인지에 따라 지퍼도 유용 할 것입니다
jk.

내 문제를보다 좁게 지정하려면 그래프 다시 작성을 기반으로하는 람다 미적분학 평가 기와 같은 그래프 다시 작성 시스템을 프로그래밍한다고 가정 해보십시오.
Alexey

1
@Alexey : 그래프 재 작성에 대한 Clean 사람들의 작업에 익숙하십니까? wiki.clean.cs.ru.nl/…
조르지오

1
@Alexey : 알지 못함 : Clean은 자체 개발 한 Haskell의 사촌입니다. 또한 부작용을 처리하는 메커니즘이 다릅니다 (AFAIK는 고유 한 유형이라고 함). 반면에 개발자들은 그래프 재 작성 작업을 많이했습니다. 따라서 그래프 재 작성과 함수형 프로그래밍에 대해 모두 알고있는 최고의 사람들이 될 수 있습니다.
Giorgio

1
지퍼를 사용하여 현재 연결된 지점을 탐색하고 수정하려는 경우 이중 연결 목록 또는 나무의 문제를 해결하는 것으로 보이지만 여러 지점에 집중하려는 경우 어떻게해야하는지 명확하지 않습니다. 예를 들어, 두 요소를 멀리 떨어진 두 곳에서 동시에 교환합니다. "원형"구조와 함께 사용할 수 있는지 확실하지 않습니다.
Alexey

2

Haskell은 변경 가능한 데이터 구조의 사용을 막지 않습니다. 그것들을 사용하는 코드 부분은 결국 IO 액션 (주 함수에 의해 반환되는 IO 액션에 바인딩되어야 함)을 반환해야한다는 사실 때문에 크게 낙담하고 사용하기가 어렵습니다. 실제로 필요한 경우 그러한 구조를 사용하는 것이 불가능합니다.

소프트웨어 트랜잭션 메모리 사용 방법을 조사하는 것이 좋습니다. 변경 가능한 구조를 구현하는 효율적인 방법을 제공 할뿐만 아니라 스레드 안전성을 매우 유용하게 보장합니다. https://hackage.haskell.org/package/stm 의 모듈 설명 및 https://wiki.haskell.org/Software_transactional_memory 의 위키 개요를 참조하십시오 .


고마워, 나는 STM에 대해 배우려고 노력할 것이다. 가변성 및 상태를 (내가시 비틀 거림을했습니다 가지고 하스켈에 더 많은 방법이있는 것 같습니다 MVar, State, ST) 내가 그 차이를 알아 내야하고 사용을위한 것입니다, 그래서.
Alexey

@Alexey : ST, IMO 에 관한 좋은 점은 상태 저장 계산을 실행 한 다음 상태를 버리고 결과를 순수한 값으로 추출 할 수 있기 때문에 답에 언급해야합니다.
Giorgio

@ Giorgio, Haskell ST을 STM과 함께 사용 하여 동시성 및 일회용 상태를 모두 사용할 수 있습니까?
Alexey

용어 제안 하나만 추가하면, 구성된 기본 IO 동작은 " 주 함수에 의해 반환 되지"않고 main변수에 할당됩니다 . :) ( main기능조차 보유하지 않습니다.)
Alexey

나는 당신의 요점을 알지만 여전히 "가변"은 대부분의 사람들의 마음에 가치를 만들어내는 과정 이라기보다는 단순한 가치로 내포되어 있으며, 주된 것이 분명히 전자보다는 후자라고 생각하는 것이 더 낫습니다. 당신이 제안한 변화는 기술적으로는 정확하지만 주제에 익숙하지 않은 사람들을 혼동 할 가능성이 있습니다.
Jules
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.