결합기는 무엇이며 프로그래밍 프로젝트에 어떻게 적용됩니까? (실제 설명)


51

결합기는 무엇입니까?

내가 찾고 있어요:

  • 실용적인 설명
  • 그것들이 어떻게 사용되는지의 예
  • 결합기가 코드의 품질 / 일반성을 향상시키는 방법의 예

찾고 있지 않습니다 :

  • 작업을 수행하는 데 도움이되지 않는 콤비 네이터에 대한 설명 (예 : Y- 콤비 네이터)

조합자는 "부사 (adverb)"와 유사하며, 함수를 취한 다음 다른 함수를 반환하는 함수입니다. 변수 사이에 필요하지 않기 때문에 코드 중복을 제거하는 데 도움이 될 수 있습니다. 몇 가지 유용한 것은 (fg) x = f (g (x)와 같이 두 번 (f) = \ x-> f (f (x)), flip (op)-> \ xy-> y op x, (.)입니다. )), ($)는 ($ 5) <$> [(+1), (* 2)] = [6, 10]에서와 같이 map (<fix> infix)에 도움을 줄 수 있습니다. 카레는 Lisp에서 사용할 수 있습니다 / Python / JavaScript (부분 응용 프로그램 용) 및 uncurry는 Haskell에서 레코드 (튜플)가 필요한 함수에 사용할 수 있습니다. x |> f = fa 인 경우 x |> (길이 &&& sum) |> uncurry (/)는 평균입니다.
aoeu256

답변:


51

실용적인 관점에서 콤비 네이터는 재미 있고 종종 고급 방식으로 논리 조각을 조합 할 수있는 일종의 프로그래밍 구조입니다. 일반적으로 그것들을 사용하는 것은 실행 가능한 코드를 람다 함수 또는 람다식이라고 불리는 (이전의 이유로) 객체로 묶을 수있는 가능성에 달려 있지만 마일리지는 다를 수 있습니다.

(유용한) 콤비 네이터의 간단한 예는 매개 변수없이 두 개의 람다 함수를 사용하여 순서대로 실행하는 새 함수를 만드는 것입니다. 실제 콤비 네이터는 다음과 같이 일반적인 의사 코드로 보입니다.

func in_sequence(first, second):
  lambda ():
    first()
    second()

이것을 결합 자로 만드는 중요한 것은 두 번째 줄의 익명 함수 (람다 함수)입니다. 전화 할 때

a = in_sequence(f, g)

결과 개체 A는 없는 제 F (), 그리고 g ()를 실행 한 결과, 그러나 만약 시퀀스 F () 및 g ()를 실행하기 위해 나중에 호출 할 수있는 것을 목적으로한다 :

a() // a is a callable object, i.e. a function without parameters

그런 다음 두 코드 블록을 병렬로 실행하는 결합기를 가질 수 있습니다.

func in_parallel(first, second):
  lambda ():
    t1 = start_thread(first)
    t2 = start_thread(second)
    wait(t1)
    wait(t2)

그리고 다시

a = in_parallel(f, g)
a()

멋진 점은 'in_parallel'과 'in_sequence'는 모두 동일한 유형 / 서명을 가진 결합기입니다. 즉, 두 개의 매개 변수가없는 함수 객체를 가져 와서 새로운 것을 반환합니다. 실제로 다음과 같은 것을 쓸 수 있습니다.

a = in_sequence(in_parallel(f, g), in_parallel(h, i))

예상대로 작동합니다.

기본적으로 컴비 네이터를 사용하면 절차적이고 유연한 방식으로 프로그램의 제어 흐름을 구성 할 수 있습니다. 예를 들어, in_parallel (..) 콤비 네이터를 사용하여 프로그램에서 병렬 처리를 실행하는 경우 in_parallel 콤비 네이터 자체의 구현에 이와 관련된 디버깅을 추가 할 수 있습니다. 나중에 프로그램에 병렬 처리 관련 버그가 있다고 생각되면 실제로 in_parallel을 다시 구현할 수 있습니다.

in_parallel(first, second):
  in_sequence(first, second)

한 번의 스트로크로 모든 병렬 섹션이 순차적 인 섹션으로 변환되었습니다!

조합기는 올바르게 사용될 때 매우 유용합니다.

그러나 Y 조합기는 실생활에서 필요하지 않습니다. 자체 재귀 함수를 만들 수있는 결합기이며 Y 조합기를 사용하지 않고도 현대 언어로 쉽게 만들 수 있습니다.


9

Y- 콤비 네이터를 "작업을 수행하는 데 도움이되지 않는"것으로 브랜드화하는 것은 잘못입니다. 많은 경우에 매우 유용하다는 것을 알았습니다. 가장 명확한 경우는 내장 된 해석 언어를 빠르게 부트 스트랩해야하는 경우입니다. 당신이 프리미티브의 최소 세트를 제공하는 경우, 즉 sequence, select, call, consta는 closure allocation, 그것은 완전한 임의의 복잡한 언어를 구축하기위한 이미 충분하다. 재귀에 대한 특별한 지원이 필요하지 않습니다. 고정 소수점 결합기를 통해 추가 할 수 있습니다. 그렇지 않으면 훨씬 더 복잡한 프리미티브가 필요합니다.

결합기의 또 다른 명백한 사례는 난독 화입니다. SKI 미적분학으로 변환 된 코드는 실제로 읽을 수 없습니다. 알고리즘의 구현을 난독 화해야 할 경우 결합기를 사용하는 것을 고려 하십시오 . 여기에 예가 있습니다.

물론 결합기는 기능적 언어를 구현하는 데 중요한 도구입니다. 위의 예와 같이 가장 쉬운 방법은 SKI 또는 이와 동등한 미적분을 사용하는 것입니다. 수퍼 콤비 네이터 는 다른 구현에 사용됩니다. 이 책 은 그것에 대해 깊이 이야기합니다.

많은 프로그래밍 기술과 이론이 여기에 포함되어 있기 때문에 이것은 농담 이지만 매우 신중하게 읽을 가치가있는 농담입니다.


1
@MattFenwick은 간단한 내장형 인터프리터를 필요로하지 않는 경우가 종종 있습니다. 예를 들어, 제 경우에는 통신 프로토콜을 확장하기 위해 디자인해야하는 언어였습니다. 간단한 IPC로는 충분하지 않았으므로 프로토콜은 실행 가능해야했습니다.
SK-logic

@MattFenwick, 귀하의 질문에 관해서는 : APL 또는 J로 코드를 작성해 볼 수 있습니다. 컴비 네이터가 필수적이므로 코드를 올바르게 적용하는 방법에 대한 아이디어를 얻을 수 있습니다. 또한 포인트 프리 스타일을 읽는 것이 도움이 될 수 있습니다. en.wikipedia.org/wiki/Tacit_programming
SK-logic

7

약간 파고 들자 나는 StackOverflow 질문, 이 질문의 가까운 사촌 인 "Combinators"(수학자가 아닌 사람들)에 대한 좋은 설명을 발견했습니다 . 답변 중 하나는 지적 레지날드 Braithwaite에의 블로그, Homoiconic (예 : 코드 콤비의 몇 가지 유용한 예제로 연결, K 개의 콤비 루비의 구현, Object#tap- 유용 이유의 예는 페이지를 읽는 방법).

Combinatory LogicWikipedia 페이지는 전체적으로 결합기를 설명합니다.


이것은 내 질문의 두 번째 글 머리 기호를 다룹니다. 예를 주셔서 감사합니다!

1
이 게시물에는 좋은 링크가 있지만 실제로 질문에 직접 대답하지는 않습니다. 답변은 자체적으로 작성해야하며 필요한 경우 링크를 참조로 사용하십시오.
Aaronaught
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.