6
\$\begingroup\$

I recently heard about functional reactive programming and thought it was rather interesting. Therefore, I started out with writing a simple program which processes a list of tasks.

(In this example, the "tasks" are just some strings which need to be printed)

So because I have no idea how to do it "right" in frp and because I'm unexperienced in Haskell, I wanted to ask, whether someone wants to take a look at it and suggest some improvements.

(The code is heavily based on the Reactive Banana examples):

import Reactive.Banana
import Reactive.Banana.Frameworks

import Data.Maybe
import Data.Foldable

type Task = String

main :: IO ()
main = do
    let printTasks :: [Task]
        printTasks = ["Hi", "there!", "Hello", "FRP!"]

    eTrigger <- newAddHandler
    network <- setupNetwork eTrigger printTasks (taskHandler eTrigger)
    actuate network
    fire eTrigger ()

taskHandler :: EventSource () -> Task -> IO()
taskHandler eTrigger task = do
  print task
  fire eTrigger ()

{-----------------------------------------------------------------------------
    Event sources
------------------------------------------------------------------------------}
-- Event Sources - allows you to register event handlers
-- Your GUI framework should provide something like this for you
type EventSource a = (AddHandler a, a -> IO ())

addHandler :: EventSource a -> AddHandler a
addHandler = fst

fire :: EventSource a -> a -> IO ()
fire = snd

{-
    Helpers
-}

tryTail = drop 1
tryFst = listToMaybe
tryDo = traverse_

{-----------------------------------------------------------------------------
    Program logic
------------------------------------------------------------------------------}
-- Set up the program logic in terms of events and behaviors.
setupNetwork :: EventSource () -> [Task] -> (Task -> IO()) -> IO EventNetwork
setupNetwork eSource printTasks taskHandler = compile $ do
    eTrigger <- fromAddHandler (addHandler eSource)

    bTasks <- accumB ("":printTasks) $ tryTail <$ eTrigger
    let bTask = tryFst <$> bTasks

    eTasksChange <- changes bTask

    reactimate' $ fmap (tryDo taskHandler) <$> eTasksChange

The library: https://wiki.haskell.org/Reactive-banana

\$\endgroup\$
4
  • \$\begingroup\$ tryTail, tryFst and tryDo are drop 1, listToMaybe and traverse_. \$\endgroup\$
    – Gurkenglas
    Jun 3, 2017 at 23:15
  • \$\begingroup\$ @Gurkenglas, thank you! Before writing helper functions I should better check Hoogλe. I edited the implementations, but kept the names, because they describe for what purpose they are used in this context. I'm not sure whether that is a "good practice". \$\endgroup\$
    – APlessner
    Jun 5, 2017 at 18:39
  • \$\begingroup\$ If tryTail was to work like tryHead (as opposed to tryFst, which I would a priori assume to have something to do with fst), I would expect it to return a Maybe [a]. Novice readers will hardly be able to guess better at the meanings, and the additional name would do as much good as a comment anyways since each is used only once. \$\endgroup\$
    – Gurkenglas
    Jun 6, 2017 at 1:09
  • \$\begingroup\$ You should add what your code is supposed to do. \$\endgroup\$
    – Zeta
    Jun 7, 2017 at 11:07

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.