All Projects → turion → Rhine

turion / Rhine

Haskell Functional Reactive Programming framework with type-level clocks

Programming Languages

haskell
3896 projects

Projects that are alternatives of or similar to Rhine

Pai
Resource scheduling and cluster management for AI
Stars: ✭ 2,223 (+3121.74%)
Mutual labels:  hacktoberfest, scheduling
Laravel Totem
Manage Your Laravel Schedule From A Web Dashboard
Stars: ✭ 1,299 (+1782.61%)
Mutual labels:  hacktoberfest, scheduling
Azkaban
Azkaban workflow manager.
Stars: ✭ 3,914 (+5572.46%)
Mutual labels:  hacktoberfest, scheduling
Cylc Flow
Cylc: a workflow engine for cycling systems. Repository master branch: core meta-scheduler component of cylc-8 (in development); Repository 7.8.x branch: full cylc-7 system.
Stars: ✭ 154 (+123.19%)
Mutual labels:  hacktoberfest, scheduling
Optaplanner
AI constraint solver in Java to optimize the vehicle routing problem, employee rostering, task assignment, maintenance scheduling, conference scheduling and other planning problems.
Stars: ✭ 2,454 (+3456.52%)
Mutual labels:  hacktoberfest, scheduling
timer.cljs
Scheduling async operations in Clojurescript
Stars: ✭ 22 (-68.12%)
Mutual labels:  clock, scheduling
Quartznet
Quartz Enterprise Scheduler .NET
Stars: ✭ 4,825 (+6892.75%)
Mutual labels:  hacktoberfest, scheduling
Escpos Printer Db
Database of ESC/POS thermal receipt printers
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Sceptre
Build better AWS infrastructure
Stars: ✭ 1,160 (+1581.16%)
Mutual labels:  hacktoberfest
Elmyr
A utility to make Kotlin/Java tests random yet reproducible
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Vue Lunar Calendar
A vue component for lunar calendar.
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Solid
Liquid template engine in Elixir
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Indico
Indico - A feature-rich event management system, made @ CERN, the place where the Web was born.
Stars: ✭ 1,160 (+1581.16%)
Mutual labels:  hacktoberfest
Ratp Api Rest
This project turnkey is distributed as a middleware to expose RATP realtime data as REST resources
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Terraform Aws Airflow
Terraform module to deploy an Apache Airflow cluster on AWS, backed by RDS PostgreSQL for metadata, S3 for logs and SQS as message broker with CeleryExecutor
Stars: ✭ 69 (+0%)
Mutual labels:  hacktoberfest
Openwisp Network Topology
Network topology collector and visualizer. Collects network topology data from dynamic mesh routing protocols or other popular networking software like OpenVPN, allows to visualize the network graph, save daily snapshots that can be viewed in the future and more.
Stars: ✭ 67 (-2.9%)
Mutual labels:  hacktoberfest
Fury
FURY - Free Unified Rendering in pYthon.
Stars: ✭ 68 (-1.45%)
Mutual labels:  hacktoberfest
Birolipsum
Birolipsum é um gerador de Lorem Ipsum com citações do (infelizmente) presidente do Brasil, Jair Bolsonaro (ou Biroliro para os íntimos).
Stars: ✭ 69 (+0%)
Mutual labels:  hacktoberfest
Parse Sdk Js
The JavaScript SDK for the Parse Platform
Stars: ✭ 1,158 (+1578.26%)
Mutual labels:  hacktoberfest
Anime Downloader
A simple but powerful anime downloader and streamer.
Stars: ✭ 1,155 (+1573.91%)
Mutual labels:  hacktoberfest

README


Build Status Version on Hackage

Rhine is a library for synchronous and asynchronous Functional Reactive Programming (FRP). It separates the aspects of clocking, scheduling and resampling from each other, and ensures clock-safety on the type level.

Complex reactive programs often process data at different rates. For example, games, GUIs and media applications may output audio and video signals, or receive user input at unpredictable times. Coordinating these different rates is a hard problem in general. If not enough care is taken, buffer underruns and overflows, space and time leaks, accidental synchronisation of independent sub-systems, and concurrency issues, such as deadlocks, may all occur.

Rhine tackles these problems by annotating the signal processing components with clocks, which hold the information when data will be input, processed and output. Different components of the signal network will become active at different times, or work at different rates. If components running under different clocks need to communicate, it has to be decided when each component becomes active ("scheduling"), and how data is transferred between the different rates ("resampling"). Rhine separates all these aspects from each other, and from the individual signal processing of each subsystem. It offers a flexible API to all of them and implements several reusable standard solutions. In the places where these aspects need to intertwine, typing constraints on clocks come into effect, enforcing clock safety.

Example

A typical example, which can be run as cd rhine-examples/ && cabal run Demonstration, would be:

  -- | Create a simple message containing the time stamp since initialisation,
  --   for each tick of the clock.
  --   Since 'createMessage' works for arbitrary clocks (and doesn't need further input data),
  --   it is a 'Behaviour'.
  --   @[email protected] is the 'TimeDomain' of any clock used to sample,
  --   and it needs to be constrained in order for time differences
  --   to have a 'Show' instance.
  createMessage
    :: (Monad m, Show (Diff time))
    => String
    -> Behaviour m time String
  createMessage str
    =   timeInfoOf sinceInit >-> arr show
    >-> arr (("Clock " ++ str ++ " has ticked at: ") ++)

  -- | Output a message /every second/ (= every 1000 milliseconds).
  --   Let us assume we want to assure that 'printEverySecond'
  --   is only called every second,
  --   then we constrain its type signature with the clock @Millisecond [email protected]
  printEverySecond :: Show a => ClSF IO (Millisecond 1000) a ()
  printEverySecond = arrMCl print

  -- | Specialise 'createMessage' to a specific clock.
  ms500 :: ClSF IO (Millisecond 500) () String
  ms500 = createMessage "500 MS"


  ms1200 :: ClSF IO (Millisecond 1200) () String
  ms1200 = createMessage "1200 MS"

  -- | Create messages every 500 ms and every 1200 ms,
  --   collecting all of them in a list,
  --   which is output every second.
  main :: IO ()
  main = flow $
    ms500 @@ waitClock            --  a Rhine = a ClSF in the context of a Clock
    ||@ scheduleMillisecond @||   --  compose 2 Rhines in parallel
    ms1200 @@ waitClock           --  a Rhine
    >-- collect                   --  buffer results from both Rhines into a list
        [email protected] concurrently          --  the next Rhine executes in its own thread
    -->
    printEverySecond @@ waitClock --  the final Rhine

  -- | Uncomment the following for a type error (the clocks don't match):

  -- typeError = ms500 >>> printEverySecond

This repository

  • rhine/: The main library, which is also mirrored on hackage.
  • rhine-gloss/: A wrapper library to gloss, a functional OpenGL library.
  • rhine-examples/: Different examples as a starting point to learn Rhine.

Documentation

The best way to learn about Rhine is currently the article Rhine: FRP with Type-Level Clocks.

For a quick reference of the most important concepts, see the cheatsheet.

Additional documentation

FAQ

  • Why does my blocking code, e.g. arrMCl readLn, behave erratically?

Clocks must be the only things that block a thread, not ClSFs. So for example, you can fix:

arrMCl readLn

by using:

tagS >>> arr read :: ClSF IO StdinClock () Int

tagS contains the string that the StdinClock grabbed from stdin, and only the clock has been allowed to block the thread!

  • Can a sampling schedule dynamically change, e.g. depend on a signal?

Yes, for instance you could implement a distance-dependent collision detector.

  • How to handle slow computations, i.e. computations that take longer than the sample rate?

Several strategies exist and it depends on your use case. For FixedStep clocks, it won't matter since the execution of the program isn't tied to a realtime clock. For ClSFs running on UTCTime clocks, you can execute the slow code in a separate thread and coordinate merging the results back into the signal network.

Development

See Contributing.md for details.

  • Rhine usually follows up-to-date GHC versions.
  • Contributions are welcome! There are always a few issues labelled help needed, in case you're looking for an easy way to get started.
  • Rhine is a beginner-friendly Haskell project! Even if you're new to Haskell and FRP, you can contribute. This is a good place to start contributing to open-source projects. Have a look at issues labelled good first issue. If you have questions, don't hesitate to ask on Github.

Related projects

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].