{"id":13800153,"url":"https://github.com/funkia/purescript-turbine","last_synced_at":"2026-02-05T04:33:51.947Z","repository":{"id":58222738,"uuid":"126343677","full_name":"funkia/purescript-turbine","owner":"funkia","description":"Purely functional UI library powered by FRP.","archived":false,"fork":false,"pushed_at":"2019-12-15T07:37:28.000Z","size":391,"stargazers_count":81,"open_issues_count":1,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-12T20:28:31.298Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/funkia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-22T13:59:51.000Z","updated_at":"2025-08-20T13:19:50.000Z","dependencies_parsed_at":"2022-08-31T03:00:47.502Z","dependency_job_id":null,"html_url":"https://github.com/funkia/purescript-turbine","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/funkia/purescript-turbine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funkia%2Fpurescript-turbine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funkia%2Fpurescript-turbine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funkia%2Fpurescript-turbine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funkia%2Fpurescript-turbine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/funkia","download_url":"https://codeload.github.com/funkia/purescript-turbine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funkia%2Fpurescript-turbine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29111918,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T03:44:17.043Z","status":"ssl_error","status_checked_at":"2026-02-05T03:44:12.077Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T00:01:09.881Z","updated_at":"2026-02-05T04:33:51.931Z","avatar_url":"https://github.com/funkia.png","language":"PureScript","readme":"# purescript-turbine\n\n[![Turbine on Pursuit](https://pursuit.purescript.org/packages/purescript-turbine/badge)](https://pursuit.purescript.org/packages/purescript-turbine)\n[![Build status](https://travis-ci.org/funkia/purescript-turbine.svg?branch=master)](https://travis-ci.org/funkia/purescript-turbine)\n\nA purely functional library for building user interfaces powered by FRP.\n\n* Based on higher-order FRP with support for continuous time.\n* Concise and powerful thanks to FRP.\n* No big global state/model. Everything is encapsulated in components.\n* Type-safe communication between views and models.\n* Model logic and view code is kept separate for logic-less views.\n* Highly modular and composable thanks to encapsulated stateful components.\n* Avoids using virtual DOM by utilizing FRP to make all changes to the DOM in reaction to changing behaviors.\n* Easy to reason about thanks to tractable reactive data flow.\n\n## Table of contents\n\n* [Inline Examples](#inline-examples)\n* [Examples](#examples)\n* [Installation](#installation)\n* [Documentation](#documentation)\n\n## Inline Examples\n\n### Single counter\n\n![single counter GIF](examples/counters/single-counter.gif)\n\n```purescript\ncounter id = component \\on -\u003e do\n  count \u003c- accum (+) 0 on.change\n  ( H.div {} (\n      H.text \"Counter \" \u003c/\u003e\n      H.span {} (H.textB $ map show count) \u003c/\u003e\n      H.button {} (H.text \"+\" ) `use` (\\o -\u003e { change: o.click $\u003e 1 }) \u003c/\u003e\n      H.button {} (H.text \"-\" ) `use` (\\o -\u003e { change: o.click $\u003e -1 })\n    )\n  ) `output` {}\n\nmain = runComponent \"#mount\" (counter 0)\n```\n\n### List of counters\n\nShow a list of counters. New counters can be added to the list. Existing\ncounters can be deleted. The aggregated sum of all the counters is shown.\n\n![list of counters GIF](examples/counters/list-counter.gif)\n\n```purescript\ncounter id = component \\on -\u003e do\n  count \u003c- accum (+) 0 on.change\n  ( H.div {} (\n      H.text \"Counter \" \u003c/\u003e\n      H.span {} (H.textB $ map show count) \u003c/\u003e\n      H.button {} (H.text \"+\" ) `use` (\\o -\u003e { change: o.click $\u003e 1 }) \u003c/\u003e\n      H.button {} (H.text \"-\" ) `use` (\\o -\u003e { change: o.click $\u003e -1 }) \u003c/\u003e\n      H.button {} (H.text \"x\") `use` (\\o -\u003e { delete: o.click })\n    )\n  ) `output` { count, delete: on.delete $\u003e id }\n\ncounterList init = component \\on -\u003e do\n  let sum = on.listOut \u003e\u003e= (map (_.count) \u003e\u003e\u003e foldr (lift2 (+)) (pure 0))\n  let removeId = map (fold \u003c\u003c\u003c map (_.delete)) on.listOut\n  let removeCounter = map (\\i -\u003e filter (i /= _)) (shiftCurrent removeId)\n  nextId \u003c- scan (+) 0 (on.addCounter $\u003e 1)\n  let appendCounter = cons \u003c$\u003e nextId\n  counterIds \u003c- accum ($) init (appendCounter \u003c\u003e removeCounter)\n  ( H.div {} (\n      H.h1 {} (H.text \"Counters\") \u003c/\u003e\n      H.span {} (H.textB (map (\\n -\u003e \"Sum \" \u003c\u003e show n) sum)) \u003c/\u003e\n      H.button {} (H.text \"Add counter\") `use` (\\o -\u003e { addCounter: o.click }) \u003c/\u003e\n      list (\\id -\u003e counter id `use` identity) counterIds identity `use` (\\o -\u003e { listOut: o })\n    )\n  ) `output` {}\n\nmain = runComponent \"#mount\" (counterList [0])\n```\n\n## Installation\n\nThe following installs Hareactive and Turbine. Hareactive is the FRP library\nthat Turbine builds upon and is a hard dependency.\n\n```\nnpm i @funkia/hareactive\nbower install --save purescript-hareactive\nnpm i @funkia/turbine\nbower install --save purescript-turbine\n```\n\nAlternatively, use the\n[purescript-turbine-starter](https://github.com/funkia/purescript-turbine-starter),\na project template that contains Turbine and Hareactive pre-setup.\n\n## Documentation\n\nThe best place to start is the [getting started\ntutorial](/docs/getting-started-tutorial.md). It is a quick start tutorial\nwhich aims to explain the basics of Turbine as briefly as possible.\n\nThere is also an older, slightly outdated, [tutorial](./docs/tutorial.md).\n\nBoth [API documentation for\nTurbine](https://pursuit.purescript.org/packages/purescript-turbine) and [API\ndocumentation for\nHareactive](https://pursuit.purescript.org/packages/purescript-hareactive) is\non Pursuit.\n\nTaking a look at the [examples](#example) is also a great way to see Turbine\nused in practice and to see how specific things are accomplished.\n\n## Examples\n\n- [Email validator](/examples/email-validator) -- A simple email validator.\n- [Fahrenheit celsius converter](/examples/fahrenheit-celsius) -- Conversion between fahrenheit and celsius.\n- [Counters](/examples/counters) -- A list of counters. This example shows how to create a dynamic list of components.\n- [Continuous time](/examples/continuous-time) -- A very simple example showing how to work with continuous time.\n- [Timer](/examples/timer) -- A more complicated example demonstrating continuous time by implementing a timer with a progress bar.\n- [Zip codes](/examples/zip-codes) -- A zip code validator. Shows how to perform `Effect`s using FRP.\n- [TodoMVC](/examples/todomvc) -- The classic TodoMVC example (still has a couple of bugs and no routing).\n\n","funding_links":[],"categories":["UI Libraries"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunkia%2Fpurescript-turbine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffunkia%2Fpurescript-turbine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunkia%2Fpurescript-turbine/lists"}