2015-09-01 17 views
7

Tôi có một giao diện (WX) dựa trên phản ứng chuối. Bây giờ tôi có câu hỏi khác nhau về làm thế nào để thực sự quản lý tình trạng:Phản ứng chuối: Nhà nước monad hay không?

  1. Tôi có nên xem xét tình trạng như Behavior s mà tôi xác định trong mã?

  2. Nếu trạng thái phụ thuộc vào "sự kiện" bên ngoài, không chỉ liên quan đến GUI sẽ xem xét tốt hơn IORef?

  3. Hoặc tôi có thể sử dụng đơn vị trạng thái không? Tất cả các ví dụ tôi đã thấy cho đến bây giờ xác định mạng trong môi trường IO. Có bất kỳ ngăn xếp ý thức nào State Monad và cách thực hiện không? Với Moment?

Trả lời

4

Tôi có nên coi trạng thái là Hành vi mà tôi xác định trong mã không?

Đối với hầu hết các trường hợp, bạn thực sự sẽ muốn sử dụng Behavior s cho tiểu bang. Trong một ứng dụng GUI, bạn sẽ thường xuyên muốn cập nhật trạng thái của bạn để đáp ứng với các sự kiện giao diện. Ngoài ra, và quan trọng, nhà nước phải duy trì hiện tại giữa các lần xuất hiện của các sự kiện và State không cho phép điều đó. Cụ thể hơn, cách tiêu chuẩn để phản ứng với một lần xuất hiện sự kiện làm điều gì đó khác hơn là cập nhật một Behavior là thông qua việc reactimate chức năng:

reactimate :: Frameworks t => Event t (IO()) -> Moment t() 

Các hành động được thực hiện là loại IO(). Trong khi có thể sử dụng runStateT để chạy tính toán StateT s IO bằng cách sử dụng reactimate, tính toán sẽ được khép kín và bạn sẽ không có trạng thái mà nó được sử dụng có sẵn để được chuyển đi nơi khác. Vấn đề này không phát sinh khi sử dụng Event s để cập nhật Behavior s thông qua giao diện FRP phản ứng chuối: Behavior s vẫn còn đó cho đến khi bạn cần sử dụng lại chúng.

Nếu trạng thái phụ thuộc vào "sự kiện" bên ngoài, không chỉ liên quan đến GUI sẽ tốt hơn là xem xét IORef?

Không nhất thiết. Trong nhiều trường hợp, bạn có thể sử dụng các công cụ trong Reactive.Banana.Frameworks chẳng hạn như fromAddHandlernewEvent để tạo Event s được kích hoạt khi các hành động I/O bên ngoài xảy ra. Bằng cách đó bạn có thể tích hợp các hành động như vậy vào mạng sự kiện của bạn. Một ví dụ điển hình là a timer: chuối phản ứng không có khái niệm thời gian tích hợp, nhưng bạn có thể giới thiệu một sự kiện đánh dấu được kích hoạt thông qua một hành động I/O diễn ra đều đặn.

Điều đó nói rằng, trong một số trường hợp, bạn vẫn có thể muốn sử dụng ...

  • ... IORef s (hoặc loại khác của các biến có thể thay đổi, chẳng hạn như MVar s), nếu bạn phải sử dụng thư viện có giao diện, vì bất kỳ lý do nào, hạn chế khả năng của bạn tự do phản ứng với các sự kiện bằng cách sử dụng Behavior s và reactimate. Một thời gian trước đây đã có a very nice question about such a scenario involving hArduino. Hai câu trả lời cho thấy khác nhau, nhưng tương tự về tinh thần, cách để có một mạng sự kiện hữu ích trong những hoàn cảnh không thuận lợi.

  • ... StateT nếu bạn có một số thuật toán trạng thái đó là khép kín và có kết quả sẽ không được sử dụng ở những nơi khác trong mạng sự kiện của bạn, do đó bạn có thể chạy nó với runStateT và dính vào nó trong một cuộc gọi reactimate. Ví dụ ngớ ngẩn: một hành động IO() trong reactimate cùng những dòng này:

    displayMessageBox . show =<< evalStateT someStateComputation initialState 
    
+0

Cảm ơn bạn! Tôi thích ý tưởng về việc kích hoạt newEvent khi hành động I/O bên ngoài xảy ra. Tôi sử dụng các giải pháp tương tự cho CQRS tại nơi làm việc nhưng không bao giờ nghĩ đến việc sử dụng nó cho một ứng dụng GUI. – Randomize

Các vấn đề liên quan