Package

purescript-turbine

Repository
funkia/purescript-turbine
License
MIT
Uploaded by
paldepind
Published on
2018-09-05

Turbine is a purely functional frontend framework powered by FRP.

  • Concise and powerful thanks to FRP.
  • No big global state/model. Everything is incapsulated in components.
  • Type-safe communication between views and models.
  • Model logic and view code is kept seperate for logic-less views.

Examples

Single counter

single counter GIF

counterModel {increment, decrement} init = do
  let changes = (increment $> 1) <> (decrement $> -1)
  count <- sample $ scan (+) init changes
  pure {count}

counterView {count} =
  E.text "Counter " </>
  E.span (E.textB $ map show count) </>
  E.button "+" `output` (\o -> {increment: o.click}) </>
  E.button "-" `output` (\o -> {decrement: o.click})

counter = modelView counterModel counterView

main = runComponent "#mount" (counter 0)

List of counters

Show a list of counters. New counters can be added to the list. Existing counters can be deleted. The aggregated sum of all the counters is shown.

list of counters GIF

counterModel {increment, decrement, delete} id = do
  let changes = (increment $> 1) <> (decrement $> -1)
  count <- sample $ scan (+) 0 changes
  pure {count, delete: delete $> id}

counterView {count} =
  E.div (
    E.text "Counter" </>
    E.span (E.textB $ map show count) </>
    E.button "+" `output` (\o -> {increment: o.click}) </>
    E.button "-" `output` (\o -> {decrement: o.click}) </>
    E.button "x" `output` (\o -> {delete: o.click})
  )

counter = modelView counterModel counterView

counterListModel {addCounter, listOut} init = do
  let sum = listOut >>= (map (_.count) >>> foldr (lift2 (+)) (pure 0))

  let removeId = map (fold <<< map (_.delete)) listOut
  let removeCounter = map (\i -> filter (i /= _)) (switchStream removeId)

  nextId <- sample $ scanS (+) 0 (addCounter $> 1)
  let appendCounter = cons <$> nextId

  counterIds <- sample $ scan ($) init (appendCounter <> removeCounter)
  pure {sum, counterIds}

counterListView {sum, counterIds} =
  E.div (
    E.h1 (E.text "Counters") </>
    E.span (E.textB (map (\n -> "Sum " <> show n) sum)) </>
    E.button "Add counter" `output` (\o -> {addCounter: o.click}) </>
    list counter counterIds id `output` (\o -> {listOut: o})
  )

counterList = modelView counterListModel counterListView

main = runComponent "#mount" (counterList [0])