以下は、反応性バナナライブラリーを使用するHaskell FRPプログラムの例です。私はちょうどハスケルと一緒に自分のやり方を感じ始めているだけで、特にFRPの意味を頭に入れていない。 https://gist.github.com/1099712は:私は本当に要旨はここにあります私は反応性バナナを使用していますか?
{-# LANGUAGE DeriveDataTypeable #-}
module Main where
{-
Example FRP/zeromq app.
The idea is that messages come into a zeromq socket in the form "id state". The state is of each id is tracked until it's complete.
-}
import Control.Monad
import Data.ByteString.Char8 as C (unpack)
import Data.Map as M
import Data.Maybe
import Reactive.Banana
import System.Environment (getArgs)
import System.ZMQ
data Msg = Msg {mid :: String, state :: String}
deriving (Show, Typeable)
type IdMap = Map String String
-- | Deserialize a string to a Maybe Msg
fromString :: String -> Maybe Msg
fromString s =
case words s of
(x:y:[]) -> Just $ Msg x y
_ -> Nothing
-- | Map a message to a partial operation on a map
-- If the 'state' of the message is "complete" the operation is a delete
-- otherwise it's an insert
toMap :: Msg -> IdMap -> IdMap
toMap msg = case msg of
Msg id_ "complete" -> delete id_
_ -> insert (mid msg) (state msg)
main :: IO()
main = do
(socketHandle,runSocket) <- newAddHandler
args <- getArgs
let sockAddr = case args of
[s] -> s
_ -> "tcp://127.0.0.1:9999"
putStrLn ("Socket: " ++ sockAddr)
network <- compile $ do
recvd <- fromAddHandler socketHandle
let
-- Filter out the Nothings
justs = filterE isJust recvd
-- Accumulate the partially applied toMap operations
counter = accumE M.empty $ (toMap . fromJust <$> justs)
-- Print the contents
reactimate $ fmap print counter
actuate network
-- Get a socket and kick off the eventloop
withContext 1 $ \ctx ->
withSocket ctx Sub $ \sub -> do
connect sub sockAddr
subscribe sub ""
linkSocketHandler sub runSocket
-- | Recieve a message, deserialize it to a 'Msg' and call the action with the message
linkSocketHandler :: Socket a -> (Maybe Msg -> IO()) -> IO()
linkSocketHandler s runner = forever $ do
receive s [] >>= runner . fromString . C.unpack
以下のコードのいくつかの批判をいただければと思います。
私は、これがaccumEの「良い」使用であるかどうかについてのコメントを特に歓迎します(私は推測していませんが、毎回この関数の全体がイベントストリーム全体をトラバースします)。
また、私は、複数のソケットからメッセージを引き出す方法について知りたいと思います。今のところ、永遠に1つのイベントループがあります。これの具体的な例として、カウンタ内のIdMapの現在の状態を照会するために、2番目のソケット(zeromq構文でREQ/REPペア)を追加する方法はありますか?
ありがとうございました。 FRPでは、ここではうまくフィットするように見えますが、多くのzeromqソケットがあれば、GUIからのイベント駆動型の入力に非常に簡単に似せるようになるでしょう...だから私はいくつかの新しいアイデアのタイヤをキックします:-) State Monadとhaskellスレッドでこれを行う方が理に適っていると思いますか? –
@Ben Ford:答えに小さな言葉を追加しました。私はあなたがソケットで何をしたいのか分からないので、あなたの目的のためにFRPが過労であるかどうかは分かりません。基本的に、イベントネットワークが単一の 'accumE'といくつかの' filterE'を持つこれよりもはるかに大きくならないなら、それはFRPなしでもっと優雅に行われます。 –