development

기능적인 GUI 프로그래밍이 가능합니까?

big-blog 2020. 2. 22. 11:43
반응형

기능적인 GUI 프로그래밍이 가능합니까? [닫은]


나는 최근에 FP 버그를 발견했고 (Haskell을 배우려고 노력 중), 지금까지 본 것 (일류 함수, 게으른 평가 및 다른 모든 장점)에 깊은 인상을 받았습니다. 나는 아직 전문가는 아니지만 기본 알고리즘보다 명령 적으로 "기능적으로"추론하기가 더 쉽다는 것을 이미 발견했다 (그리고 내가 필요한 곳으로 돌아가는 데 어려움을 겪고있다).

그러나 현재 FP가 평평하게 떨어지는 영역 중 하나는 GUI 프로그래밍입니다. Haskell 접근 방식은 명령형 GUI 툴킷 (GTK + 또는 wxWidgets 등)을 랩핑하고 명령 식 스타일을 시뮬레이션하기 위해 "do"블록을 사용하는 것 같습니다. F #을 사용하지는 않았지만 .NET 클래스와 함께 OOP를 사용하여 비슷한 것을 수행한다는 것을 이해합니다. 분명히 현재의 GUI 프로그래밍은 IO와 부작용에 관한 것이므로 당연히 기능적인 프로그래밍은 대부분의 최신 프레임 워크에서는 불가능합니다.

내 질문은 GUI 프로그래밍에 대한 기능적 접근 방식이 가능합니까? 실제로 이것이 어떻게 보일지 상상하는 데 어려움을 겪고 있습니다. 실험이나 다른 방법으로 이런 종류의 것을 시도하는 프레임 워크 (또는 기능적 언어를 위해 처음부터 설계된 프레임 워크)를 아는 사람이 있습니까? 아니면 GUI 부분에는 OOP를, 논리에는 FP를 사용하여 하이브리드 방식을 사용하는 솔루션입니까? (나는 단지 호기심을 요구하고있다. 나는 FP가 "미래"라고 생각하고 싶지만 GUI 프로그래밍은 꽤 큰 구멍처럼 보인다.)


Haskell 접근 방식은 명령형 GUI 툴킷 (GTK + 또는 wxWidgets 등)을 래핑하고 "do"블록을 사용하여 명령 식 스타일을 시뮬레이션하는 것으로 보입니다.

이것이 바로 "Haskell 방식"이 아니라 명령형 인터페이스를 통해 명령형 GUI 툴킷에 가장 직접적으로 바인딩하는 방법입니다. Haskell은 상당히 두드러진 바인딩을 가지고 있습니다.

대부분 Haskell에서 주로 기능적 반응성 프로그래밍을 사용하는 GUI에 대한 완만하게 성숙하거나 실험적인 순전히 기능적 / 선언적 접근 방식이 있습니다.

몇 가지 예는 다음과 같습니다.

Haskell, Flapjax, http://www.flapjax-lang.org/에 익숙하지 않은 분들을 위해 JavaScript 기반의 기능적 반응성 프로그래밍을 구현했습니다.


내 질문은 GUI 프로그래밍에 대한 기능적 접근 방식이 가능합니까?

찾고있는 핵심어는 "기능적 반응성 프로그래밍"(FRP)입니다.

Conal Elliott와 일부 다른 사람들은 FRP에 대한 올바른 추상화를 찾으려고 약간의 코티지 산업을 만들었습니다. Haskell에는 몇 가지 FRP 개념 구현이 있습니다.

Conal의 최신 "Push-Pull Functional Reactive Programming" 논문 으로 시작하는 것을 고려할 수도 있지만 haskell.org 사이트 에서 링크 된 다른 (구형) 구현이 몇 가지 더 있습니다 . Conal은 전체 영역을 다루는 요령을 가지고 있으며, 그의 논문은 이전의 내용을 참조하지 않고도 읽을 수 있습니다.

이 접근법이 GUI 개발에 어떻게 사용될 수 있는지에 대한 느낌을 얻으려면, Fudgets 를보고 싶을 것입니다. 요즘 90 년대 중반에 설계 되었지만 오늘날 에는 조금 길어지고 있지만 견고한 FRP 접근 방식을 보여줍니다. GUI 디자인.


Windows Presentation Foundation 은 기능적 접근 방식이 GUI 프로그래밍에 매우 효과적이라는 증거입니다. 많은 기능적 측면이 있으며 "좋은"WPF 코드 (MVVM 패턴 검색)는 명령에 대한 기능적 접근 방식을 강조합니다. WPF가 가장 성공적인 실제 기능 GUI 툴킷이라고 용감하게 주장 할 수 있습니다. :-)

WPF는 XAML의 사용자 인터페이스를 설명하지만 (기능적으로 보이는 C # 또는 F #로 다시 작성할 수는 있지만) 사용자 인터페이스를 만들 수 있습니다.

<!-- Declarative user interface in WPF and XAML --> 
<Canvas Background="Black">
   <Ellipse x:Name="greenEllipse" Width="75" Height="75" 
      Canvas.Left="0" Canvas.Top="0" Fill="LightGreen" />
</Canvas>

또한 WPF를 사용하면 다른 선언적 태그 세트를 사용하여 이벤트에 대한 애니메이션 및 반응을 선언적으로 설명 할 수 있습니다 (다시 말하면 C # / F # 코드로 작성 될 수 있음).

<DoubleAnimation
   Storyboard.TargetName="greenEllipse" 
   Storyboard.TargetProperty="(Canvas.Left)"
   From="0.0" To="100.0" Duration="0:0:5" />

실제로 WPF에는 Haskell의 FRP와 공통점이 많이 있다고 생각합니다 (WPF 디자이너는 FRP에 대해 알지 못했고 약간 불행한 것으로 생각하지만 WPF는 때로는 기능을 사용하면 약간 이상하고 불분명하다고 느낍니다. 관점).


실제로 함수형 프로그래밍 (F #)이 C #보다 사용자 인터페이스 프로그래밍에 훨씬 더 좋은 도구라고 말하고 싶습니다. 문제에 대해 조금 다르게 생각하면됩니다.

16 장의 함수형 프로그래밍에서이 주제에 대해 설명 하지만 , F #에서 사용할 수있는 가장 흥미로운 패턴 인 (IMHO)를 보여주는 무료 발췌문이 있습니다 . 사각형 그리기를 구현한다고 가정하십시오 (사용자가 버튼을 누르고 마우스를 움직이고 버튼을 놓습니다). F #에서는 다음과 같이 작성할 수 있습니다.

let rec drawingLoop(clr, from) = async { 
   // Wait for the first MouseMove occurrence 
   let! move = Async.AwaitObservable(form.MouseMove) 
   if (move.Button &&& MouseButtons.Left) = MouseButtons.Left then 
      // Refresh the window & continue looping 
      drawRectangle(clr, from, (move.X, move.Y)) 
      return! drawingLoop(clr, from) 
   else
      // Return the end position of rectangle 
      return (move.X, move.Y) } 

let waitingLoop() = async { 
   while true do
      // Wait until the user starts drawing next rectangle
      let! down = Async.AwaitObservable(form.MouseDown) 
      let downPos = (down.X, down.Y) 
      if (down.Button &&& MouseButtons.Left) = MouseButtons.Left then 
         // Wait for the end point of the rectangle
         let! upPos = drawingLoop(Color.IndianRed, downPos) 
         do printfn "Drawn rectangle (%A, %A)" downPos upPos }

이는 매우 일반적인 접근 방식 (일반적인 실용적인 F # 스타일)이지만 현재 드로잉 상태를 저장하고 초기 위치를 저장하기 위해 변경 가능한 상태를 사용하지 않습니다. 그래도 좀 더 기능적으로 만들 수 있으며, 석사 논문의 일부로이 기능을 수행하는 라이브러리를 작성했습니다.이 논문 은 다음 며칠 내 내 블로그 에서 사용할 수 있습니다 .

Functional Reactive Programming은보다 기능적인 접근 방법이지만 화살표와 같은 고급 Haskell 기능에 의존하기 때문에 사용하기가 다소 어렵습니다. 그러나 많은 경우에 매우 우아합니다. 제한적인 것은 상태 머신 (반응 형 프로그램에 유용한 멘탈 모델)을 쉽게 인코딩 할 수 없다는 것입니다. 위의 F # 기술을 사용하면 매우 쉽습니다.


F # 또는 OCaml과 같은 하이브리드 기능 / OO 언어 또는 부작용이 IO 모나드로 강등되는 Haskell과 같은 순수 기능 언어에 관계 없이 GUI를 관리하는 데 많은 작업이 필요한 경우가 대부분입니다 순전히 기능적인 알고리즘보다 "부작용"과 훨씬 비슷합니다.

기능적인 GUI에 대한 확실한 연구가 있었다 . Fudgets 또는 FranTk 와 같은 기능적 툴킷도 있습니다.


Don Syme의 F #에서 시리즈를 확인하여 데모를 작성하는 GUI를 확인할 수 있습니다. 다음 링크는 시리즈의 세 번째 파트에 대한 것입니다 (여기에서 다른 두 파트로 링크 할 수 있음).

WPF 개발에 F #을 사용하는 것은 매우 흥미로운 GUI 패러다임입니다.

http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/


Functional Reactive Programming의 기본 개념 중 하나는 이벤트에 대한 반응과 다음 이벤트 처리 기능을 생성하는 이벤트 처리 기능을 갖는 것입니다. 따라서 진화하는 시스템은 일련의 이벤트 처리 기능으로 표현됩니다.

저에게 Yampa에 대한 학습은 그 기능 생성 기능을 올바르게 얻는 중요한 결정이되었습니다. Yampa에 관한 좋은 논문이 있습니다. 나는 Yampa Arcade를 추천합니다 :

http://www.cs.nott.ac.uk/~nhn/Talks/HW2003-YampaArcade.pdf (슬라이드, PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003. pdf (전체 기사, PDF)

Yampa의 Haskell.org에 위키 페이지가 있습니다

http://www.haskell.org/haskellwiki/Yampa

오리지널 얌파 홈페이지 :

http://www.haskell.org/yampa (불행히도 현재는 망가졌습니다)


FRP에 대한 Elliot의 연설은 여기 에서 찾을 수 있습니다 .

또한, 실제로는 대답이 아니라 발언과 몇 가지 생각이 있습니다 . "기능성 GUI"라는 용어는 옥시 모론과 같은 것 같습니다 (동일한 순도 및 IO).

그러나 나의 모호한 이해는 기능적 GUI 프로그래밍이 (실시간) 의존적 사용자 입력을 취하고 시간 의존적 GUI 출력을 생성하는 시간 의존적 기능을 선언적으로 정의하는 것에 관한 것이다.

다시 말해서,이 함수는 가변 상태를 사용하는 알고리즘에 의해 대신에 미분 방정식처럼 선언적으로 정의됩니다.

따라서 기존의 FP에서는 시간 독립적 기능을 사용하는 반면 FRP에서는 시간 종속 기능을 프로그램을 설명하기위한 빌딩 블록으로 사용합니다.

사용자가 상호 작용할 수있는 스프링에서 공을 시뮬레이션하는 것에 대해 생각해 봅시다. 공의 위치는 그래픽 출력 (화면)이며 공을 누르는 사용자는 키 누름 (입력)입니다.

FRP에서이 시뮬레이션 프로그램을 설명하는 것은 (내 이해에 따라) 단일 미분 방정식 (선언적으로)으로 수행됩니다. 가속 * 질량 =-스프링 스트레치 * 스프링 상수 + 사용자가 가한 힘.

다음은 이 관점을 보여주는 ELM 비디오입니다 .


이 질문이 처음 제기 된 이후, 기능적 반응성 프로그래밍은 Elm에 의해 좀 더 주류가되었습니다.

http://elm-lang.org 에서 확인하는 것이 좋습니다 . 여기에는 완전한 기능을 갖춘 브라우저 내 GUI를 만드는 방법에 대한 훌륭한 대화식 자습서도 있습니다.

사용자가 직접 제공해야하는 코드가 순수한 기능으로 만 구성되는 GUI를 완벽하게 작동시킬 수 있습니다. 개인적으로 다양한 Haskell GUI 프레임 워크보다 훨씬 쉽게 접근 할 수있었습니다.


2016 년 현재, 하스켈에 대해 나트륨 및 리플렉스 (및 Netwire)와 같은 비교적 성숙한 FRP 프레임 워크가 몇 가지 더 있습니다.

매닝의 기능 반응성 프로그래밍에 대한 책 쇼케이스 작업 예제 나트륨의 자바 버전, 그리고 비교의 FRP GUI 코드베이스의 동작합니다 비늘이 배우를 기반 접근 방식뿐만 아니라 명령형하는 방법을 보여줍니다.

Arrowized FRP에 대한 최근 논문과 법을 준수하는 순수한 FRP 설정에 부작용, IO 및 돌연변이를 통합 할 수있는 전망도 있습니다 : http://haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-formatted-dissertation.pdf .

또한 ReactJS 및 Angular와 같은 JavaScript 프레임 워크는 이미 확장 가능하고 구성 가능한 GUI 구성 요소를 달성하기 위해 FRP 또는 기타 기능적 접근 방식을 사용 중이거나 이미 진행 중입니다.


XUL과 같은 마크 업 언어를 사용하면 선언적인 방식으로 GUI를 작성할 수 있습니다.


이 문제를 해결하기 위해 F #을 사용하여 내 생각을 게시했습니다.

http://fadsworld.wordpress.com/2011/04/13/f-in-the-enterprise-i/ http://fadsworld.wordpress.com/2011/04/17/fin-the-enterprise-ii- 2 /

또한 시리즈를 마무리하고 F #이 UX 프로그래밍에 기여하는 방법을 보여주기 위해 비디오 자습서를 만들 계획입니다.

F #의 맥락에서만 이야기하고 있습니다.

파하드


다른 모든 답변은 함수형 프로그래밍을 기반으로 작성되지만 자체 디자인 결정을 많이 내립니다. 기본적으로 함수와 간단한 추상 데이터 형식으로 완전히 만들어진 하나의 라이브러리는 gloss입니다. play소스 기능 유형은 다음과 같습니다.

-- | Play a game in a window. Like `simulate`, but you manage your own input events.
play    :: Display              -- ^ Display mode.
        -> Color                -- ^ Background color.
        -> Int                  -- ^ Number of simulation steps to take for each second of real time.
        -> world                -- ^ The initial world.
        -> (world -> Picture)   -- ^ A function to convert the world a picture.
        -> (Event -> world -> world)    
                -- ^ A function to handle input events.
        -> (Float -> world -> world)
                -- ^ A function to step the world one iteration.
                --   It is passed the period of time (in seconds) needing to be advanced.
        -> IO ()

보시다시피, 다른 라이브러리가 도움이되는 간단한 추상 유형으로 순수한 함수를 제공하면 완전히 작동합니다.


Haskell을 처음 접하는 사람들이 주목 한 가장 명백한 혁신은 외부 세계와의 의사 소통과 관련된 불순한 세계와 순수한 계산 및 알고리즘 세계가 분리되어 있다는 것입니다. 빈번한 초보자 질문은 "내가 제거 할 수있는 방법이다 IO, 즉, 변환을 IO aa?" 이를 수행하는 방법은 모나드 (또는 다른 추상화)를 사용하여 IO 및 체인 효과를 수행하는 코드를 작성하는 것입니다. 이 코드는 외부 세계에서 데이터를 수집하고, 모델을 생성하고, 순수한 코드를 사용하여 일부 계산을 수행하고 결과를 출력합니다.

위의 모델에 관한 한, IO모나드 에서 GUI를 조작하는 데 아무런 문제가 없습니다 . 이 스타일에서 발생하는 가장 큰 문제는 모듈을 더 이상 구성 할 수 없다는 것입니다. 즉, 프로그램에서 명령문의 전역 실행 순서에 대한 대부분의 지식을 잃습니다. 이를 복구하려면 동시 명령형 GUI 코드와 유사한 추론을 적용해야합니다. 한편, 부정확하고 GUI가 아닌 코드의 경우 IO모나드 >==연산자 의 정의 때문에 (적어도 하나의 스레드 만 있는 경우) 실행 순서가 분명 합니다. 순수한 코드의 경우 성능을 높이거나 평가 결과를 피하기 위해 코너 케이스를 제외하고는 전혀 중요하지 않습니다 .

콘솔과 그래픽 IO의 가장 큰 철학적 차이점은 전자를 구현하는 프로그램이 일반적으로 동기식 스타일로 작성된다는 것입니다. 이것은 신호와 다른 열린 파일 디스크립터를 제외하고 하나의 이벤트 소스 만 있기 때문에 가능합니다 stdin. 일반적으로 바이트 스트림이라고 합니다. GUI는 본질적으로 비동기 적이며 키보드 이벤트 및 마우스 클릭에 반응해야합니다.

기능적인 방식으로 비동기 IO를 수행하는 일반적인 철학을 FRP (Functional Reactive Programming)라고합니다. ReactiveX 와 같은 라이브러리와 Elm과 같은 프레임 워크 덕분에 최근에는 불완전하고 작동하지 않는 언어로 많은 관심을 받았습니다 . 간단히 말해서 GUI 요소 및 기타 항목 (예 : 파일, 시계, 알람, 키보드, 마우스)을 이벤트 스트림을 발생시키는 "관찰 가능"이라고하는 이벤트 소스로 보는 것과 같습니다. 이러한 이벤트는 다음과 같은 친숙한 연산자를 사용하여 결합 map, foldl, zip, filter, concat, join, 등, 새로운 스트림을 생성 할 수 있습니다. 이것은 프로그램 상태 자체가 scanl . map reactToEvents $ zipN <eventStreams>프로그램에서 볼 수 있기 때문에 유용합니다 . 여기서 프로그램에서 N고려한 관측 가능 수와 같습니다.

FRP 옵저버 블을 사용하면 스트림의 이벤트가 제 시간에 정렬되므로 작곡 성을 복구 할 수 있습니다. 이벤트 스트림 추상화는 모든 관찰 가능 항목을 블랙 박스로 볼 수 있기 때문입니다. 궁극적으로 연산자를 사용하여 이벤트 스트림을 결합하면 실행시 로컬 순서가 다시 결정됩니다. 이로 인해 Haskell의 모든 함수가 참조 적으로 투명 해야하는 방식과 유사하게 내 프로그램이 실제로 의존하는 변수에 대해 훨씬 더 정직해야합니다. 프로그램의 다른 부분에서 데이터를 가져 오려면 명시 적이어야합니다. 내 기능에 적합한 유형을 선언하십시오. (불순한 코드를 작성하기위한 도메인 별 언어 인 IO 모나드는이를 효과적으로 우회합니다)


함수형 프로그래밍은 제가 대학에있을 때부터 시작되었을 수도 있지만, 함수형 프로그래밍 시스템의 요점은 프로그래머가 "부작용"을 일으키는 것을 막는 것이 었습니다. 그러나 사용자는 UI 업데이트와 같은 부작용으로 인해 소프트웨어를 구매합니다.

참고 URL : https://stackoverflow.com/questions/2672791/is-functional-gui-programming-possible



반응형