화살의 목적은 무엇입니까?


62

나는 Haskell과 함께 함수형 프로그래밍을 배우고 있으며, 왜 필요한지 먼저 이해함으로써 개념을 잡으려고 노력합니다.

함수형 프로그래밍 언어에서 화살표의 목표를 알고 싶습니다. 그들은 어떤 문제를 해결합니까? http://en.wikibooks.org/wiki/Haskell/Understanding_arrowshttp://www.cse.chalmers.se/~rjmh/afp-arrows.pdf 확인했습니다 . 내가 이해하는 것은 계산을 위해 그래프를 설명하는 데 사용되며 더 쉬운 포인트 프리 스타일 코딩이 가능하다는 것입니다.

이 기사에서는 포인트 프리 스타일이 일반적으로 이해하고 작성하기 쉽다고 가정합니다. 이것은 나에게 매우 주관적인 것 같습니다. 다른 기사 ( http://en.wikibooks.org/wiki/Haskell/StephensArrowTutorial#Hangman:_Main_program )에서 행맨 게임이 구현되었지만 화살표 가이 구현을 어떻게 자연스럽게 만드는지 알 수 없습니다.

나는 개념을 설명하는 많은 논문을 찾을 수 있지만 동기 부여에 대해서는 아무것도 없습니다.

내가 무엇을 놓치고 있습니까?

답변:


42

나는 파티에 늦게 온다는 것을 알고 있지만 여기에 두 가지 이론적 대답이 있었고, 씹을 수있는 실용적인 대안을 제공하고 싶었습니다. 그럼에도 불구하고 나는 현재 진행중인 프로젝트에 대해 Arrows 주제를 통해 최근에 강제 행진 한 Haskell 멍청한 친척으로 여기에 왔습니다.

첫째, Arrows에 도달하지 않고도 Haskell의 대부분의 문제를 생산적으로 해결할 수 있습니다. 일부 주목할만한 Haskellers는 진정으로 싫어하고 사용하지 않습니다 (자세한 내용은 여기 , 여기여기 참조). 당신이 자신에게 "이봐, 난 필요 없어"라고 말하는 경우에, 당신이 진정으로 정확할 수 있음을 이해하십시오.

내가 처음 화살표를 배웠을 때 내가 화살표에 대해 가장 실망한 것은 주제의 튜토리얼이 필연적으로 회로의 비유를 위해 어떻게 도달했는지였습니다. 최소한 설탕을 넣은 품종 인 Arrow 코드를 보면 하드웨어 선언 언어와 전혀 흡사합니다. 입력은 오른쪽에 정렬되고 출력은 왼쪽에 정렬되며 모두 올바르게 연결하지 않으면 단순히 작동하지 않습니다. 나는 나 자신에게 생각했다 : 정말로? 우리가 끝난 곳입니까? 우리는 다시 한번 구리선과 납땜으로 구성된 언어를 완전히 고수준으로 만들었습니까?

내가 결정할 수있는 한 이것에 대한 정답은 실제로입니다. 현재 Arrows의 킬러 사용 사례는 FRP입니다 (Yampa, 게임, 음악 및 반응 형 시스템을 일반적으로 생각하십시오). FRP가 직면 한 문제는 다른 모든 동기식 메시징 시스템이 직면 한 것과 거의 같은 문제입니다. 관련 정보를 삭제하거나 스프링 누수없이 연속적인 입력 스트림을 연속적인 출력 스트림에 연결하는 방법입니다. 스트림을 목록으로 모델링 할 수 있습니다 (최근의 여러 FRP 시스템에서이 방법을 사용함). 입력 목록이 많은 경우 관리하기가 거의 불가능합니다. 현재로부터 자신을 격리시켜야합니다.

FRP 시스템에서 Arrows가 허용하는 기능은 네트워크로 기능을 구성하는 동시에 해당 기능에 의해 전달되는 기본 값에 대한 참조를 완전히 추상화하는 것입니다. FP를 처음 사용하는 경우 처음에는 혼란 스러울 수 있으며 그 의미를 흡수했을 때 마음이 번질 수 있습니다. 최근에는 함수를 추상화 할 수 있다는 아이디어와 [(*), (+), (-)]유형 유형 과 같은 목록을 이해하는 방법 만 이해했습니다 [(a -> a -> a)]. 화살표를 사용하면 추상화를 한 계층 더 밀어 낼 수 있습니다.

추상화하는 이러한 추가 능력은 그 자체의 위험을 수반합니다. 우선, GHC를 사용하여 유형 가정을 무엇을 해야할지 모를 경우 코너에 넣을 수 있습니다. 유형 수준에서 생각할 준비가되어 있어야합니다. 이것은 종류와 RankNType 및 기타 주제에 대해 배울 수있는 좋은 기회입니다.

또한 "Stupid Arrow Stunts"라고하는 몇 가지 예가 있습니다. 코더는 튜플을 사용하여 깔끔한 트릭을 보여주기 위해 Arrow 컴비 네이터에 도달합니다. (여기서 광기에 기여한 사소한 일이 있습니다.) 야생에서 만날 때 그러한 핫도그를 무시하십시오.

참고 : 위에서 언급했듯이 나는 상대 멍청한 놈입니다. 위의 오해를 공표 한 경우 언제든지 수정 해주세요.


2
아직 아무것도받지 않았다 니 다행입니다. 이 답변을 제공해 주셔서 감사합니다. 사용자에게 더 중점을 둡니다. 모범은 위대하다. 주관적인 부분은 명확하게 정의되고 균형이 잡 힙니다. 이 질문에 찬성 한 사람들이 다시 와서 이것을 보길 바랍니다.
Simon Bergot

화살표는 귀하의 연결된 솔루션에 대한 잘못된 도구이지만, 나는 removeAt' n = arr(\ xs -> (xs,xs)) >>> arr (take (n-1)) *** arr (drop n) >>> arr (uncurry (++)) >>> returnA더 간결하고 명확하게 쓰여질 수 있다고 언급해야한다고 생각합니다 removeAt' n = (arr (take $ n-1) &&& arr (drop n)) >>> (arr $ uncurry (++)).
cemper93

29

이것은 일종의 "부드러운"답변이며, 어떤 참조가 실제로 이런 식으로 그것을 언급하는지 확실하지 않지만, 이것이 화살표를 생각하게 된 방법입니다.

화살표 유형 A b c은 기본적으로 함수 b -> c이지만, 모나드 값 M a이 평범한 것보다 더 많은 구조 를 갖는 것과 같은 방식으로 더 많은 구조를 갖습니다 a.

이제 그 추가 구조는 무슨 특정 화살표 인스턴스에 따라 달라집니다. 모나드 IO a와 마찬가지로 Maybe a각각 추가 구조가 다릅니다.

당신이 모나드로 얻을 것은은에서 이동하는 무능력이다 M aa. 이제 이것은 제한적인 것처럼 보일 수 있지만 실제로는 기능입니다. 타입 시스템은 모노 값을 평범한 오래된 값으로 바꾸는 것을 방지합니다. >>=특정 모나드 인스턴스의 프리미티브 또는 비아 나드를 통해 모나드에 참여하여 값을 사용할 수 있습니다 .

마찬가지로 당신이 얻는 것은 A b c새로운 b 소비 c 생성 "함수"를 구성 할 수 없다는 것입니다 . 화살표는 다양한 화살표 결합기에 참여하거나 특정 화살표 인스턴스의 기본 작업을 사용하여 제외 b및 소비를 방지합니다 c.

예를 들어 Yampa의 신호 기능은 대략적인 (Time -> a) -> (Time -> b)것이지만, 추가로 특정 인과 관계 제한 을 준수해야합니다 . 시간의 출력 t은 입력 신호의 과거 값에 의해 결정됩니다. 그래서 그들이하는 것은로 프로그래밍하는 대신 (Time -> a) -> (Time -> b), 당신 은로 프로그래밍하고 SF a b프리미티브에서 신호 기능을 구축합니다. 너무 이후가 발생 SF a b하는 일반적인 구조는 "화살표"라고 무엇 때문에, 함수처럼 많이 작동합니다.


"화살표는 다양한 화살표 조합에 참여하거나 특정 화살표 인스턴스의 기본 작업을 사용하여 제외 b및 소비를 방지합니다 c." 이 고대 답변에 대한 답변으로 사과와 함께 :이 문장은 선형 유형, 즉 자원을 복제하거나 소멸시킬 수 없다고 생각하게했습니다. 당신은 어떤 연결이있을 수 있다고 생각하십니까?
glaebhoerl

14

나는 Monads와 Functors와 같은 Arrows를 프로그래머가 이국적인 기능 구성을 할 수있게한다고 생각하고 싶다.

Monads 또는 Arrows (및 Functors)가 없으면 기능 언어의 기능 구성은 한 기능을 다른 기능의 결과에 적용하는 것으로 제한됩니다. 모나드와 펑터를 사용하면 두 개의 함수를 정의한 다음 특정 모나드의 맥락에서 해당 함수가 서로 상호 작용하는 방식과 전달 된 데이터와 상호 작용하는 방식을 지정하는 별도의 재사용 가능한 코드를 작성할 수 있습니다. 이 코드는 Monad의 바인드 코드 내에 배치됩니다. 따라서 모나드는 하나의 뷰이며 재사용 가능한 바인드 코드의 컨테이너입니다. 함수는 한 모나드의 컨텍스트 내에서 다른 모나드와 다르게 구성됩니다.

간단한 예는 Maybe 모나드인데, bind 함수에 코드가있어 함수 A가 Maybe 모나드 내의 함수 B로 구성되고 B가 Nothing을 생성하면 바인드 코드는 두 함수는 B에서 나오는 Nothing 값에 A를 적용하지 않고 Nothing을 출력합니다. 모나드가 없으면 프로그래머는 Nothing 입력을 테스트하기 위해 A에 코드를 작성해야합니다.

Monads는 또한 프로그래머가 각 함수에 필요한 매개 변수를 소스 코드에 명시 적으로 입력 할 필요가 없음을 의미합니다. bind 함수는 매개 변수 전달을 처리합니다. 따라서 모나드를 사용하면 소스 코드는 함수 A가 매개 변수 C와 D를 사용하여 함수 B를 호출하는 것처럼 보이지 않고 함수 이름의 정적 체인처럼 보일 수 있습니다. 코드는 전자 회로처럼 느껴집니다 움직이는 기계-명령보다 더 기능적입니다.

화살표는 또한 기능을 바인드 기능과 함께 연결하여 재사용 가능한 기능을 제공하고 매개 변수를 숨 깁니다. 그러나 Arrows 자체는 서로 연결하여 구성 할 수 있으며 런타임에 데이터를 다른 Arrows로 라우팅 할 수도 있습니다. 이제 데이터에 "다른 일"을하는 두 개의 화살표 경로에 데이터를 적용하고 결과를 다시 어셈블 할 수 있습니다. 또는 데이터의 일부 값에 따라 데이터를 전달할 화살표 분기를 선택할 수 있습니다. 결과 코드는 스위치, 지연, 통합 등을 포함한 전자 회로와 훨씬 비슷합니다. 프로그램은 매우 정적 인 것처럼 보이므로 진행중인 데이터 조작을 많이 볼 수 없습니다. 생각해야 할 매개 변수가 점점 더 적고 매개 변수가 취할 수있는 값과 그렇지 않을 수있는 값에 대해 생각할 필요가 없습니다.

Arrowized 프로그램을 작성하려면 대부분 스플리터, 스위치, 지연 및 통합 기와 같은 선반 화살표를 선택하고, 해당 화살표로 기능을 들어 올리고, 화살표를 함께 연결하여 더 큰 화살표를 만듭니다. Arrowized Functional Reactive Programming에서 화살표는 월드의 입력이 프로그램의 마지막 반복의 출력과 결합되어 출력이 실제 입력에 반응하도록 루프를 형성합니다.

실제 가치 중 하나는 시간입니다. Yampa에서 신호 기능 화살표는 컴퓨터 프로그램을 통해 시간 매개 변수를 보이지 않게 스레드합니다. 시간 값에 액세스 할 수는 없지만 적분기 화살표를 프로그램에 연결하면 시간이 지남에 따라 통합 된 값이 출력됩니다. 다른 화살표.


그러나 이것은 applicative functor (함수 주위의 일부 랩퍼)처럼 들립니다. 일부 특정 컨텍스트에서 랩핑 된 유형의 기존 함수를 재사용하기 위해 도우미 함수를 제공합니다. 나는 이해하기 위해 더 많은 것을 읽을 필요가 있지만, 내가 잃어버린 것을 지적함으로써 도울 수 있습니다.
Belun

3

다른 답변에 추가하면 : 개인적으로 그러한 개념이 무엇인지 (수학적으로) 이해하고 그것이 내가 아는 다른 개념과 어떻게 관련되는지 이해하는 데 도움이됩니다.

화살표의 경우, 나는 다음과 같은 용지가 도움이되었다고합니다 - 그것은 모나드, 실용적 펑 (숙어)과 화살을 비교 : 숙어는 잊기, 화살표 세심, 모나드가 문란하다 샘 린, 필립와 들러와 제레미 Yallop에 의해.

또한 주제에 대한 아이디어와 문헌을 제공 할 수있는 이 링크 를 언급 한 사람은 아무도 없습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.