https://wiki.haskell.org/api.php?action=feedcontributions&user=Turion&feedformat=atomHaskellWiki - User contributions [en]2020-01-19T12:50:26ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Web/Libraries/CSS&diff=62926Web/Libraries/CSS2019-06-05T16:13:14Z<p>Turion: Added Clay</p>
<hr />
<div>[[Category:Web|*]]<br />
{{Web infobox}}<br />
<br />
== Factor CSS ==<br />
<br />
This tool takes a CSS stylesheet on input and produces an almost equivalent stylesheet on output, but with rulesets split, combined, and reordered to "factor out" common declarations. This helps reveal shared components. The resulting stylesheet may also be smaller.<br />
<br />
{| class="wikitable"<br />
! Home page:<br />
| http://zamez.org/factorcss<br />
|-<br />
! Package & repositories<br />
| [http://zamez.org/source/factorcss/ VS/SVN](?)<br />
|}<br />
<br />
== Cassius ==<br />
Part of hamlet- see [[Web/Libraries/Templating]].<br />
Insert haskell values into your stylesheets.<br />
<br />
== CSS ==<br />
<br />
Minimal monadic CSS DSL.<br />
<br />
{| class="wikitable"<br />
! License:<br />
| BSD3<br />
|-<br />
! Author:<br />
| Chris Done<br />
|-<br />
! Documentation:<br />
| [https://github.com/chrisdone/css/blob/master/README.md README]<br />
|-<br />
! Package & repositories<br />
| [http://hackage.haskell.org/package/css Hackage] - [https://github.com/chrisdone/css Github]<br />
|}<br />
<br />
<br />
== Clay ==<br />
<br />
Modern, well-documented CSS preprocessor with a Haskell DSL<br />
<br />
<br />
{| class="wikitable"<br />
! Home page:<br />
| http://fvisser.nl/clay/<br />
|-<br />
! Package & repositories<br />
| [https://github.com/sebastiaanvisser/clay github] - [http://hackage.haskell.org/package/clay hackage]<br />
|}</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62624Rhine2018-09-26T21:07:23Z<p>Turion: /* Clock safety */</p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
A 'running clock' is an effectful stream of time stamps. (The side effect can include polling the system time, a device, or waiting/blocking until a certain time.) The clock is said to tick whenever a time stamp is emitted.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
==== Events ====<br />
<br />
Event sources are also clocks in a natural sense that tick every time an event occurs.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type. <hask>a</hask> is the input data type (in this case it is arbitrary because any input is discarded), and <hask>Pos</hask> is the output data type.<br />
<br />
Being based on [https://github.com/ivanperez-keera/dunai Dunai],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
Signal functions are "clocked" and can only be composed synchronously when their clocks match. The following will not typecheck:<br />
<br />
<haskell><br />
doubleAt1Hz :: ClSF m (Millisecond 1000) Integer Integer<br />
doubleAt1Hz = arr (* 2)<br />
<br />
doubleAt2Hz :: ClSF m (Millisecond 500) Integer Integer<br />
doubleAt2Hz = arr (* 2)<br />
<br />
quadrupleAtNonsensicalRate = doubleAt1Hz >>> doubleAt2Hz<br />
</haskell><br />
<br />
<code><br />
error: * Couldn't match type `500' with `1000'<br />
[...]<br />
</code><br />
<br />
In general, clock type errors will occur when trying to compose Rhine components at non-matching clocks. This feature is called 'clock-safety'. Subsystems on different clocks have to communicate over explicitly specified resampling buffers, coordinated by explicit schedules (see sections below).<br />
<br />
==== Behaviours and clock-polymorphism ====<br />
<br />
Signal functions can be polymorphic in the clock. In that case, they are called <hask>Behaviour</hask>s, since they model the original FRP idea of a value (or function) varying with time, oblivious of the sampling/clocking strategy.<br />
<br />
=== Schedules ===<br />
<br />
A schedule for two clocks <hask>cl1</hask> and <hask>cl2</hask> is a universal clock such that <hask>cl1</hask> and <hask>cl2</hask> are subclocks. The schedule ticks exactly whenever either <hask>cl1</hask> or <hask>cl2</hask> would tick.<br />
<br />
Rhine has a number of predefined schedules, so you rarely need to implement your own. For example, you can use concurrency and let the framework run the two clocks in separate background threads, while all concurrent communication is encapsulated and hidden from the library user. For certain clocks, such as fixed-step clocks, it is also possible to schedule them 'deterministically', which is very useful when e.g. audio and video sampling ratios need to be kept stable.<br />
<br />
=== Resampling buffers ===<br />
<br />
A resampling buffer is the fundamental asynchronous data component in Rhine. It accepts <hask>put</hask> and <hask>get</hask> calls that put data into, and get data from, the buffer. Usually, these methods need not be called explicitly. Instead, resampling buffers connect synchronous signal functions that work at different rates.<br />
<br />
The Rhine library implements standard buffering and resampling techniques such as FIFO queues, linear/cubic/sinc interpolation, first order holds and others. Some buffers, like fixed-rate up-/downsamplers, are annotated with clock types in order to be used only at the correct rate. Others are clock-polymorphic.<br />
<br />
=== Main loops ===<br />
<br />
Signal functions and resampling buffers are composed to 'signal networks'. In turn, signal networks together with compatible clocks form the main high-level components, called <hask>Rhine</hask>s themselves.<br />
The library has several combinators that allow for easy creation of <hask>Rhine</hask>s from basic components.<br />
<br />
A 'closed' <hask>Rhine</hask>, i.e. one that has the trivial input and output type <hask>()</hask>, is a main loop. It is run by starting its clock, feeding the time stamps into the signal network and let it perform its side effects.<br />
<br />
All this is done automatically by the framework without inserting any additional side effects. This makes Rhine suitable for reproducible testing, since it hides no IO under the hood.<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62623Rhine2018-09-26T20:59:30Z<p>Turion: Undo revision 62621 by Turion (talk)</p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
A 'running clock' is an effectful stream of time stamps. (The side effect can include polling the system time, a device, or waiting/blocking until a certain time.) The clock is said to tick whenever a time stamp is emitted.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
==== Events ====<br />
<br />
Event sources are also clocks in a natural sense that tick every time an event occurs.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type. <hask>a</hask> is the input data type (in this case it is arbitrary because any input is discarded), and <hask>Pos</hask> is the output data type.<br />
<br />
Being based on [https://github.com/ivanperez-keera/dunai Dunai],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
Signal functions are "clocked" and can only be composed synchronously when their clocks match. The following will not typecheck:<br />
<br />
<haskell><br />
doubleAt1Hz :: ClSF m (Millisecond 1000) Integer Integer<br />
doubleAt1Hz = arr (* 2)<br />
<br />
doubleAt2Hz :: ClSF m (Millisecond 500) Integer Integer<br />
doubleAt2Hz = arr (* 2)<br />
<br />
quadrupleAtNonsensicalRate = doubleAt1Hz >>> doubleAt2Hz<br />
</haskell><br />
<br />
<code><br />
error: * Couldn't match type `500' with `1000'<br />
[...]<br />
</code><br />
<br />
In general, clock type errors will occur when trying to compose Rhine components at non-matching clocks. This feature is called _clock-safety_. Subsystems on different clocks have to communicate over explicitly specified resampling buffers, coordinated by explicit schedules (see sections below).<br />
<br />
==== Behaviours and clock-polymorphism ====<br />
<br />
Signal functions can be polymorphic in the clock. In that case, they are called <hask>Behaviour</hask>s, since they model the original FRP idea of a value (or function) varying with time, oblivious of the sampling/clocking strategy.<br />
<br />
=== Schedules ===<br />
<br />
A schedule for two clocks <hask>cl1</hask> and <hask>cl2</hask> is a universal clock such that <hask>cl1</hask> and <hask>cl2</hask> are subclocks. The schedule ticks exactly whenever either <hask>cl1</hask> or <hask>cl2</hask> would tick.<br />
<br />
Rhine has a number of predefined schedules, so you rarely need to implement your own. For example, you can use concurrency and let the framework run the two clocks in separate background threads, while all concurrent communication is encapsulated and hidden from the library user. For certain clocks, such as fixed-step clocks, it is also possible to schedule them 'deterministically', which is very useful when e.g. audio and video sampling ratios need to be kept stable.<br />
<br />
=== Resampling buffers ===<br />
<br />
A resampling buffer is the fundamental asynchronous data component in Rhine. It accepts <hask>put</hask> and <hask>get</hask> calls that put data into, and get data from, the buffer. Usually, these methods need not be called explicitly. Instead, resampling buffers connect synchronous signal functions that work at different rates.<br />
<br />
The Rhine library implements standard buffering and resampling techniques such as FIFO queues, linear/cubic/sinc interpolation, first order holds and others. Some buffers, like fixed-rate up-/downsamplers, are annotated with clock types in order to be used only at the correct rate. Others are clock-polymorphic.<br />
<br />
=== Main loops ===<br />
<br />
Signal functions and resampling buffers are composed to 'signal networks'. In turn, signal networks together with compatible clocks form the main high-level components, called <hask>Rhine</hask>s themselves.<br />
The library has several combinators that allow for easy creation of <hask>Rhine</hask>s from basic components.<br />
<br />
A 'closed' <hask>Rhine</hask>, i.e. one that has the trivial input and output type <hask>()</hask>, is a main loop. It is run by starting its clock, feeding the time stamps into the signal network and let it perform its side effects.<br />
<br />
All this is done automatically by the framework without inserting any additional side effects. This makes Rhine suitable for reproducible testing, since it hides no IO under the hood.<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62621Rhine2018-09-25T20:34:28Z<p>Turion: </p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
(Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type.)<br />
<br />
Being based on [[https://github.com/ivanperez-keera/dunai Dunai]],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
Signal functions are "clocked" and can only be composed synchronously when their clocks match. The following will not typecheck:<br />
<br />
<haskell><br />
doubleAt1Hz :: ClSF m (Millisecond 1000) Integer Integer<br />
doubleAt1Hz = arr (* 2)<br />
<br />
doubleAt2Hz :: ClSF m (Millisecond 500) Integer Integer<br />
doubleAt2Hz = arr (* 2)<br />
<br />
quadrupleAtNonsensicalRate = doubleAt1Hz >>> doubleAt2Hz<br />
</haskell><br />
<br />
<code><br />
error:<br />
* Couldn't match type `500' with `1000'<br />
[...]<br />
</code><br />
<br />
=== Schedules ===<br />
<br />
''TODO''<br />
<br />
=== Resampling buffers ===<br />
<br />
''TODO''<br />
<br />
== Behaviours and Events ==<br />
<br />
''TODO''<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62620Rhine2018-09-25T10:16:46Z<p>Turion: /* Signal functions */</p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
A 'running clock' is an effectful stream of time stamps. (The side effect can include polling the system time, a device, or waiting/blocking until a certain time.) The clock is said to tick whenever a time stamp is emitted.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
==== Events ====<br />
<br />
Event sources are also clocks in a natural sense that tick every time an event occurs.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type. <hask>a</hask> is the input data type (in this case it is arbitrary because any input is discarded), and <hask>Pos</hask> is the output data type.<br />
<br />
Being based on [https://github.com/ivanperez-keera/dunai Dunai],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
Signal functions are "clocked" and can only be composed synchronously when their clocks match. The following will not typecheck:<br />
<br />
<haskell><br />
doubleAt1Hz :: ClSF m (Millisecond 1000) Integer Integer<br />
doubleAt1Hz = arr (* 2)<br />
<br />
doubleAt2Hz :: ClSF m (Millisecond 500) Integer Integer<br />
doubleAt2Hz = arr (* 2)<br />
<br />
quadrupleAtNonsensicalRate = doubleAt1Hz >>> doubleAt2Hz<br />
</haskell><br />
<br />
<code><br />
error: * Couldn't match type `500' with `1000'<br />
[...]<br />
</code><br />
<br />
In general, clock type errors will occur when trying to compose Rhine components at non-matching clocks. This feature is called _clock-safety_. Subsystems on different clocks have to communicate over explicitly specified resampling buffers, coordinated by explicit schedules (see sections below).<br />
<br />
==== Behaviours and clock-polymorphism ====<br />
<br />
Signal functions can be polymorphic in the clock. In that case, they are called <hask>Behaviour</hask>s, since they model the original FRP idea of a value (or function) varying with time, oblivious of the sampling/clocking strategy.<br />
<br />
=== Schedules ===<br />
<br />
A schedule for two clocks <hask>cl1</hask> and <hask>cl2</hask> is a universal clock such that <hask>cl1</hask> and <hask>cl2</hask> are subclocks. The schedule ticks exactly whenever either <hask>cl1</hask> or <hask>cl2</hask> would tick.<br />
<br />
Rhine has a number of predefined schedules, so you rarely need to implement your own. For example, you can use concurrency and let the framework run the two clocks in separate background threads, while all concurrent communication is encapsulated and hidden from the library user. For certain clocks, such as fixed-step clocks, it is also possible to schedule them 'deterministically', which is very useful when e.g. audio and video sampling ratios need to be kept stable.<br />
<br />
=== Resampling buffers ===<br />
<br />
A resampling buffer is the fundamental asynchronous data component in Rhine. It accepts <hask>put</hask> and <hask>get</hask> calls that put data into, and get data from, the buffer. Usually, these methods need not be called explicitly. Instead, resampling buffers connect synchronous signal functions that work at different rates.<br />
<br />
The Rhine library implements standard buffering and resampling techniques such as FIFO queues, linear/cubic/sinc interpolation, first order holds and others. Some buffers, like fixed-rate up-/downsamplers, are annotated with clock types in order to be used only at the correct rate. Others are clock-polymorphic.<br />
<br />
=== Main loops ===<br />
<br />
Signal functions and resampling buffers are composed to 'signal networks'. In turn, signal networks together with compatible clocks form the main high-level components, called <hask>Rhine</hask>s themselves.<br />
The library has several combinators that allow for easy creation of <hask>Rhine</hask>s from basic components.<br />
<br />
A 'closed' <hask>Rhine</hask>, i.e. one that has the trivial input and output type <hask>()</hask>, is a main loop. It is run by starting its clock, feeding the time stamps into the signal network and let it perform its side effects.<br />
<br />
All this is done automatically by the framework without inserting any additional side effects. This makes Rhine suitable for reproducible testing, since it hides no IO under the hood.<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62619Rhine2018-09-25T10:16:24Z<p>Turion: </p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
A 'running clock' is an effectful stream of time stamps. (The side effect can include polling the system time, a device, or waiting/blocking until a certain time.) The clock is said to tick whenever a time stamp is emitted.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
==== Events ====<br />
<br />
Event sources are also clocks in a natural sense that tick every time an event occurs.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type. <hask>a</hask> is the input data type (in this case it is arbitrary because any input is discarded), and <hask>Pos</hask> is the output data type.<br />
<br />
Being based on [[https://github.com/ivanperez-keera/dunai Dunai]],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
Signal functions are "clocked" and can only be composed synchronously when their clocks match. The following will not typecheck:<br />
<br />
<haskell><br />
doubleAt1Hz :: ClSF m (Millisecond 1000) Integer Integer<br />
doubleAt1Hz = arr (* 2)<br />
<br />
doubleAt2Hz :: ClSF m (Millisecond 500) Integer Integer<br />
doubleAt2Hz = arr (* 2)<br />
<br />
quadrupleAtNonsensicalRate = doubleAt1Hz >>> doubleAt2Hz<br />
</haskell><br />
<br />
<code><br />
error: * Couldn't match type `500' with `1000'<br />
[...]<br />
</code><br />
<br />
In general, clock type errors will occur when trying to compose Rhine components at non-matching clocks. This feature is called _clock-safety_. Subsystems on different clocks have to communicate over explicitly specified resampling buffers, coordinated by explicit schedules (see sections below).<br />
<br />
==== Behaviours and clock-polymorphism ====<br />
<br />
Signal functions can be polymorphic in the clock. In that case, they are called <hask>Behaviour</hask>s, since they model the original FRP idea of a value (or function) varying with time, oblivious of the sampling/clocking strategy.<br />
<br />
=== Schedules ===<br />
<br />
A schedule for two clocks <hask>cl1</hask> and <hask>cl2</hask> is a universal clock such that <hask>cl1</hask> and <hask>cl2</hask> are subclocks. The schedule ticks exactly whenever either <hask>cl1</hask> or <hask>cl2</hask> would tick.<br />
<br />
Rhine has a number of predefined schedules, so you rarely need to implement your own. For example, you can use concurrency and let the framework run the two clocks in separate background threads, while all concurrent communication is encapsulated and hidden from the library user. For certain clocks, such as fixed-step clocks, it is also possible to schedule them 'deterministically', which is very useful when e.g. audio and video sampling ratios need to be kept stable.<br />
<br />
=== Resampling buffers ===<br />
<br />
A resampling buffer is the fundamental asynchronous data component in Rhine. It accepts <hask>put</hask> and <hask>get</hask> calls that put data into, and get data from, the buffer. Usually, these methods need not be called explicitly. Instead, resampling buffers connect synchronous signal functions that work at different rates.<br />
<br />
The Rhine library implements standard buffering and resampling techniques such as FIFO queues, linear/cubic/sinc interpolation, first order holds and others. Some buffers, like fixed-rate up-/downsamplers, are annotated with clock types in order to be used only at the correct rate. Others are clock-polymorphic.<br />
<br />
=== Main loops ===<br />
<br />
Signal functions and resampling buffers are composed to 'signal networks'. In turn, signal networks together with compatible clocks form the main high-level components, called <hask>Rhine</hask>s themselves.<br />
The library has several combinators that allow for easy creation of <hask>Rhine</hask>s from basic components.<br />
<br />
A 'closed' <hask>Rhine</hask>, i.e. one that has the trivial input and output type <hask>()</hask>, is a main loop. It is run by starting its clock, feeding the time stamps into the signal network and let it perform its side effects.<br />
<br />
All this is done automatically by the framework without inserting any additional side effects. This makes Rhine suitable for reproducible testing, since it hides no IO under the hood.<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62618Rhine2018-09-23T21:51:17Z<p>Turion: </p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
(Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type.)<br />
<br />
Being based on [[https://github.com/ivanperez-keera/dunai Dunai]],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
''TODO''<br />
<br />
=== Schedules ===<br />
<br />
''TODO''<br />
<br />
=== Resampling buffers ===<br />
<br />
''TODO''<br />
<br />
== Behaviours and Events ==<br />
<br />
''TODO''<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Rhine&diff=62617Rhine2018-09-23T21:50:45Z<p>Turion: Rhine, FRP library with type-level clocks</p>
<hr />
<div>Rhine is an arrowized [[FRP]] library with '''type level clocks'''. It is designed with multi-rate FRP in mind, combining synchronous arrowized FRP features (as in Yampa) with asynchronous building blocks.<br />
<br />
== Building blocks in Rhine ==<br />
<br />
There are two kinds of separation of concerns: First, temporal aspects (clocking/sampling) are separated from dataflow aspects. Second, synchronous components are separated from asynchronous ones. The situation is summarised in this table:<br />
<br />
{|<br />
|+ Aspect separation<br />
! !! Time !! Data<br />
|-<br />
! Synchronous<br />
| Clocks || Clocked signal functions<br />
|-<br />
! Asynchronous<br />
| Schedules || Resampling buffers<br />
|}<br />
<br />
=== Clocks ===<br />
<br />
In Rhine, you can annotate each (synchronous) signal function with a clock type. This clock type gives ''clock safety'' since throughout the framework it is ensured that every signal function is run at the speed of this clock.<br />
<br />
Rhine has a number of ready-to-use clocks, for example fixed-rate clocks like <haskell>Millisecond n</haskell> where <haskell>n</haskell> is a type-level natural number.<br />
<br />
=== Signal functions ===<br />
<br />
Signal functions are aware of time and internal state. Standard arrowized FRP constructions are implemented in Rhine:<br />
<br />
<haskell><br />
type Pos = (Double, Double, Double)<br />
<br />
freeFallFrom10Meters :: ClSF m cl a Pos<br />
freeFallFrom10Meters = arr (const (0,0,-9.81))<br />
>>> integral<br />
>>> integralFrom (0,0,10)<br />
</haskell><br />
<br />
(Here, <hask>m</hask> is an arbitrary monad and <hask>cl</hask> is an arbitrary clock type.)<br />
<br />
Being based on [[https://github.com/ivanperez-keera/dunai Dunai]],<br />
signal functions can also perform side effects in a monad <hask>m</hask>:<br />
<br />
<haskell><br />
exitWhenNegative :: ClSF (ExceptT () m) cl Pos ()<br />
exitWhenNegative = throwOn' <<< arr (\(_, _, z) -> (z < 0, ()))<br />
</haskell><br />
<br />
Like in standard Haskell, monad transformers need to be handled. In Rhine (and Dunai), interesting things happen when handling monad transformers. In the case of <hask>ExceptT</hask>, we have ''control flow''!<br />
<br />
<haskell><br />
freeFallThenOnTheGround :: ClSF m cl a Pos<br />
freeFallThenOnTheGround = safely $ do<br />
try $ freeFallFrom10Meters >>> (id &&& exitWhenNegative) >>> arr fst<br />
safe $ arr $ const (0, 0, 0)<br />
</haskell><br />
<br />
This little signal function simulates an object that falls from 10 meters, throws an exception when the height drops below 0, and then eternally stays at the coordinates <hask>(0, 0, 0)</hask>. This example is discussed at length in the article (link on the bottom of the page).<br />
<br />
We can also use other monads, like <hask>IO</hask>:<br />
<br />
<haskell><br />
printHeight :: ClSF IO cl a ()<br />
printHeight = freeFallThenOnTheGround >>> arrMCl print<br />
</haskell><br />
<br />
Rhine does not hide any side effects under the hood. All effects that are used are visible in the type.<br />
<br />
==== Clock safety ====<br />
<br />
''TODO''<br />
<br />
=== Schedules ===<br />
<br />
''TODO''<br />
<br />
=== Resampling buffers ===<br />
<br />
''TODO''<br />
<br />
== Behaviours and Events<br />
<br />
''TODO''<br />
<br />
== Development ==<br />
<br />
* Rhine is developed on https://github.com/turion/rhine. The development version usually stays up to date with the latest GHC. Support requests for applications developed with Rhine are very welcome there.<br />
* Rhine is on [https://www.stackage.org/package/rhine/snapshots stackage].<br />
<br />
=== General development guideline ===<br />
<br />
To build an application with Rhine, you can usually follow this guideline:<br />
<br />
# Ask yourself what the different synchronous subsystems of the whole application should be. You will recognise them by the rate they work ("tick") at. For example in a game, you might have a user event system, a physical simulation, and a graphics system.<br />
# Ask yourself whether you have any special clocks, e.g. external devices, event machines you need to connect to, external loops you have to connect to. Implement those as clocks in Rhine, ideally using existing components.<br />
# Implement each synchronous subsystem as a clocked signal function.<br />
# Decide how to schedule the different clocks. In most cases, you will be able to use deterministic or concurrent schedules from the library.<br />
# Decide how to resample the data from one subsystem to the other. Take existing resampling buffers from the library, or build your own buffers from existing ones and signal functions.<br />
# Build the main Rhine program from all the components. The clock types will tell you whether you have correctly combined everything.<br />
# Run the main loop and possibly add initialisation and clean up actions.<br />
<br />
== Further resources ==<br />
<br />
* The main article: https://www.manuelbaerenz.de/article/rhine-frp-type-level-clocks<br />
* For an example app, see https://github.com/turion/sonnendemo<br />
* Haskell Symposium 2018 presentation by Iván Pérez: To be uploaded</div>Turionhttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=62616Functional Reactive Programming2018-09-23T20:02:04Z<p>Turion: </p>
<hr />
<div>Functional Reactive Programming (FRP) integrates time flow and compositional events into functional programming. This provides an elegant way to express computation in domains such as interactive animations, robotics, computer vision, user interfaces, and simulation.<br />
<br />
<br />
== Introduction ==<br />
<br />
The original formulation of Functional Reactive Programming can be found in the ICFP 97 paper [http://conal.net/papers/icfp97/ Functional Reactive Animation] by Conal Elliott and Paul Hudak.<br />
<br />
=== Behaviors ===<br />
<br />
Traditionally a widget-based user interface is created by a series of imperative actions. First an action is invoked to create an edit widget, then additional actions can be invoked to read its current content, set it to a specific value or to assign an event callback for when the content changes. This is tedious and error-prone.<br />
<br />
A better way to represent an edit widget's content is a time-varying value, called a ''behavior''. The basic idea is that a time-varying value can be represented as a function of time:<br />
<br />
<haskell><br />
newtype Behavior a =<br />
Behavior {<br />
at :: Time -> a<br />
}<br />
<br />
myName :: Behavior Text<br />
<br />
myName `at` yesterday<br />
</haskell><br />
<br />
This is only a theoretical model, because a time-varying value can represent something impure like the content of an edit widget, the current value of a database entry as well as the system clock's current time. Using this model the current content of an edit widget would be a regular first class value:<br />
<br />
<haskell><br />
myEditWidget :: Behavior Text<br />
</haskell><br />
<br />
In most frameworks there is an applicative interface for behaviors, such that you can combine them easily:<br />
<br />
<haskell><br />
liftA2 (<>) myEdit1 myEdit2<br />
</haskell><br />
<br />
The result is a time-varying value that represents the concatenation of <hask>myEdit1</hask> and <hask>myEdit2</hask>. This could be the value of a third widget, a label, to display the concatenation. The following is a hypothetical example:<br />
<br />
<haskell><br />
do edit1 <- editWidget<br />
edit2 <- editWidget<br />
label <- label (liftA2 (<>) edit1 edit2)<br />
{- ... -}<br />
</haskell><br />
<br />
Without behaviors you would have to write event callback ''actions'' for the edit widgets to ''update'' the label's content. With behaviors you can express this relationship declaratively.<br />
<br />
=== Events ===<br />
<br />
''To do''<br />
<br />
== Libraries ==<br />
* [[DataDriven]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [http://conal.net/fran/ Fran] (discontinued)<br />
* [[Grapefruit]]<br />
* [[Netwire]]<br />
* [[Reactive]]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [http://hackage.haskell.org/package/reflex Reflex]<br />
* [http://hackage.haskell.org/package/sodium Sodium]<br />
* [[WxFruit|wxFruit]]<br />
* [[Yampa]]<br />
* [[https://github.com/ivanperez-keera/dunai Dunai]]<br />
* [[Rhine]]<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:FRP Hackage packages in the category FRP]<br />
A simple, practical comparison between FRP libraries is done by [https://github.com/gelisam/frp-zoo frp-zoo]<br />
<br />
== Publications and talks ==<br />
<br />
* [https://www.youtube.com/watch?v=zgNRM8tZguY ICFP 2014: Settable and Non-Interfering Signal Functions for FRP - Daniel Winograd-Cort] (video)<br />
* [http://www.cs.rit.edu/~eca7215/frp-independent-study/Survey.pdf A Survey of Functional Reactive Programming]<br />
* [http://conal.net/papers/frp.html Conal Elliott’s FRP-related publications]<br />
* [https://grapefruit-project.org/publications-and-talks Grapefruit-related publications and talks]<br />
* [http://haskell.cs.yale.edu/?page_id=65#FunctionalReactiveProgramming The Yale Haskell Group’s FRP-related publications]<br />
* [https://begriffs.com/posts/2015-07-22-essence-of-frp.html The Essence of FRP (Conal Elliott -- July 22, 2015 -- video)]<br />
* [https://begriffs.com/posts/2016-07-27-tikhon-on-frp.html A Sensible Intro to FRP (Tikhon Jelvis -- July 27, 2016 -- video)]<br />
<br />
== Books ==<br />
* Blackheath, Stephen; Jones, Antony. [http://www.manning.com/blackheath Functional Reactive Programming]. Manning Publications (2015). p.245. ISBN 978-1-6334-3010-5<br />
<br />
== Blog posts ==<br />
<br />
* [https://github.com/gelisam/frp-zoo frp-zoo]; comparing many FRP implementations by reimplementing the same toy app in each.<br />
* [http://blog.reactiveprogramming.org/ Functional Reactive Programming, a better way to build interactive applications] (about the Sodium FRP Library currently for C#, C++, Haskell and Java and more to come)<br />
* [http://apfelmus.nfshost.com/blog.html#functional-reactive-programming-frp FRP-related posts on Heinrich Apfelmus’ blog]<br />
* [http://conal.net/blog/tag/frp FRP-related posts on Conal Elliott’s blog]<br />
* [http://jeltsch.wordpress.com/tag/frp/ FRP-related posts on Wolfgang Jeltsch’s blog]<br />
* [http://lukepalmer.wordpress.com/2008/11/28/relative-time-frp/ Relative time FRP] by Luke Palmer<br />
* [http://blog.edwardamsden.com/2011/03/demonstrating-time-leak-in-arrowized.html Demonstrating a Time Leak in Arrowized FRP] by Edward Amsden<br />
* [https://www.reddit.com/r/haskell/comments/3fr5ij/frp_systems_discussion/ FRP Systems discussion] on reddit<br />
<br />
== People ==<br />
* [http://apfelmus.nfshost.com/ Heinrich Apfelmus]<br />
* [http://www.facebook.com/antony.courtney Antony Courtney]<br />
* [http://conal.net/ Conal Elliott]<br />
* [http://sgate.emt.bme.hu/patai/ Patai Gergely]<br />
* [http://www.ittc.ku.edu/csdl/fpg/Users/AndyGill Andy Gill]<br />
* Liwen Huang<br />
* Paul Hudak<br />
* [https://wolfgang.jeltsch.info/ Wolfgang Jeltsch]<br />
* [http://www.cs.nott.ac.uk/~nhn/ Henrik Nilsson]<br />
* [http://github.com/ivanperez-keera Ivan Perez]<br />
* [http://mcis.western.edu/~jpeterson/ John Peterson]<br />
* Ertugrul Söylemez<br />
<br />
[[Category:FRP|*]]</div>Turionhttps://wiki.haskell.org/index.php?title=Applicative_functor&diff=62472Applicative functor2018-05-07T17:09:54Z<p>Turion: Extended part about applicative transformers</p>
<hr />
<div>[[Category:Glossary]]<br />
[[Category:Applicative Functor|*]]<br />
An applicative functor has more structure than a [[functor]] but less than a [[monad]]. See the Haddock docs for [https://downloads.haskell.org/~ghc/latest/docs/html/libraries/base-4.9.0.0/Control-Applicative.html Control.Applicative].<br />
<br />
== Example ==<br />
<br />
It has turned out that many applications do not require monad functionality but only those of applicative functors.<br />
Monads allow you to run actions depending on the outcomes of earlier actions.<br />
<haskell><br />
do text <- getLine<br />
if null text<br />
then putStrLn "You refuse to enter something?"<br />
else putStrLn ("You entered " ++ text)<br />
</haskell><br />
This is obviously necessary in some cases, but in other cases it is disadvantageous.<br />
<br />
Consider an extended IO monad which handles automated closing of allocated resources.<br />
This is possible with a monad.<br />
<haskell><br />
openDialog, openWindow :: String -> CleanIO ()<br />
<br />
liftToCleanup :: IO a -> CleanIO a<br />
<br />
runAndCleanup :: CleanIO a -> IO a<br />
<br />
runAndCleanup $<br />
do text <- liftToCleanup getLine<br />
if null text<br />
then openDialog "You refuse to enter something?"<br />
else openWindow ("You entered " ++ text)<br />
</haskell><br />
The (fictive) functions <hask>openDialog</hask> and <hask>openWindow</hask><br />
could not only open dialogs and windows but could also register some cleanup routine in the <hask>CleanIO</hask>.<br />
<hask> runAndCleanup </hask> would first run the opening actions and afterwards the required cleanup actions.<br />
I.e. if the dialog was opened, the dialog must be closed, but not the window.<br />
That is, the cleanup procedure depends on the outcomes of earlier actions.<br />
<br />
Now consider the slightly different task, where functions shall register ''initialization'' routines<br />
that shall be run before the actual action takes place.<br />
(See the original discussion started by Michael T. Richter in Haskell-Cafe:<br />
[http://www.haskell.org/pipermail/haskell-cafe/2007-June/027517.html Practical Haskell Question])<br />
This is impossible in the monadic framework.<br />
Consider the example above where the choice between <hask>openDialog</hask> and <hask>openWindow</hask><br />
depends on the outcome of <hask> getLine </hask>.<br />
You cannot run initialization code for either <hask>openDialog</hask> or <hask>openWindow</hask>,<br />
because you do not know which one will be called before executing <hask> getLine </hask>.<br />
If you eliminate this dependency, you end up in an applicative functor<br />
and there you can do the initialization trick.<br />
You could write<br />
<haskell><br />
initializeAndRun $<br />
liftA2<br />
(liftToInit getLine)<br />
(writeToWindow "You requested to open a window")<br />
</haskell><br />
where <hask> writeToWindow </hask> registers an initialization routine which opens the window.<br />
<br />
== Usage ==<br />
<br />
If you have the variables<br />
<haskell><br />
f :: a -> b -> c<br />
a :: f a<br />
b :: f b<br />
</haskell><br />
you can combine them in the following ways with the same result of type <hask>f c</hask>:<br />
* <hask>pure f <*> a <*> b</hask><br />
* <hask>liftA2 f a b</hask><br />
<br />
But how to cope with <hask>let</hask> and sharing in the presence of effects?<br />
Consider the non-functorial expression:<br />
<haskell><br />
x :: x<br />
g :: x -> y<br />
h :: y -> y -> z<br />
<br />
let y = g x<br />
in h y y<br />
</haskell><br />
Very simple.<br />
Now we like to generalize this to<br />
<haskell><br />
fx :: f x<br />
fg :: f (x -> y)<br />
fh :: f (y -> y -> z)<br />
</haskell><br />
However, we note that<br />
<haskell><br />
let fy = fg <*> fx<br />
in fh <*> fy <*> fy<br />
</haskell><br />
runs the effect of <hask>fy</hask> twice.<br />
E.g. if <hask>fy</hask> writes something to the terminal then <hask>fh <*> fy <*> fy</hask> writes twice. This could be intended, but how can we achieve, that the effect is run only once and the result is used twice?<br />
<br />
Actually, using the <hask>liftA</hask> commands we can pull results of applicative functors into a scope where we can talk exclusively about functor results and not about effects. Note that functor results can also be functions. This scope is simply a function, which contains the code that we used in the non-functorial setting.<br />
<haskell><br />
liftA3<br />
(\x g h -> let y = g x in h y y)<br />
fx fg fh<br />
</haskell><br />
The order of effects is entirely determined by the order of arguments to <hask>liftA3</hask>.<br />
<br />
== Some advantages of applicative functors ==<br />
<br />
* Code that uses only the <hask>Applicative</hask> interface is more general than code that uses the <hask>Monad</hask> interface, because there are more applicative functors than monads. The <hask>ZipList</hask> is an applicative functor on lists, where <hask>liftA2</hask> is implemented by <hask>zipWith</hask>. It is a typical example of an applicative functor that is not a monad.<br />
* Programming with <hask>Applicative</hask> has a more applicative/functional feel. Especially for newbies, it may encourage functional style even when programming with effects. Monad programming with [[Do notation considered harmful|do notation]] encourages a more sequential & imperative style.<br />
<br />
== Applicative transformers ==<br />
<br />
From the [[Monad Transformer Library]] we are used to have two flavours of every monad: a base monad like <hask>State</hask> and a transformer variant <hask>StateT</hask>. In the [http://hackage.haskell.org/package/transformers/ transformers] package we even have only monad transformers except the <hask>Identity</hask> monad.<br />
So where are applicative transformers? The answer is, that in most situations, we do not need special transformers for applicative functors since they can be combined in a generic way.<br />
<haskell><br />
h :: f (g (a -> b))<br />
a :: f (g a)<br />
<br />
liftA2 (<*>) h a :: f (g b)<br />
</haskell><br />
That is, <hask>liftA2 (<*>)</hask> is essentially the definition for <hask><*></hask><br />
for the composition of the functors <hask>f</hask> and <hask>g</hask>.<br />
This is implemented in the {{HackagePackage|id=TypeCompose}} library as type constructor <hask>O</hask> and in {{HackagePackage|id=transformers}} library in module <hask>Data.Functor.Compose</hask>. The first one needs a lot of type extensions, whereas the second one is entirely Haskell 98.<br />
<br />
It can be useful to use the applicative composition even when you have a monad transformer at hand. In the example above <hask>f</hask> might be <hask>Writer (Sum Int)</hask> that is used for counting the number of involved applicative actions. Since in an applicative functor the number of run actions is independent from interim results, the writer can count the actions at compile time.<br />
<br />
It is not true that transformers are unnecessary for applicatives, though. Consider <hask>State s (IO a) == s -> (s, IO a)</hask>, which behaves like an applicative with the above trick, but it is different from <hask>StateT s IO a == s -> IO (s, a)</hask>. The latter is more useful in some situations, and it is not a composition of any two applicatives.<br />
<br />
== How to switch from monads ==<br />
<br />
* Start using <hask>liftM</hask>, <hask>liftM2</hask>, etc or <hask>ap</hask> where you can, in place of <hask>do</hask>/<hask>(>>=)</hask>. You will often encounter code like<br />
<haskell><br />
do x <- fx<br />
y <- fy<br />
return (g x y)<br />
</haskell><br />
:It can be rewritten to <hask>liftM2 g fx fy</hask>. In general, whenever the choice or construction of monadic actions does not depend on the outcomes of previous monadic actions, then it should be possible to rewrite everything with <hask>liftM</hask>.<br />
* When you notice you're ''only'' using those monad methods, then import <hask>Control.Applicative</hask> and replace<hask>return</hask> with <hask>pure</hask>, <hask>liftM</hask> with <hask>(<$>)</hask> (or <hask>fmap</hask> or <hask>liftA</hask>), <hask>liftM2</hask> with <hask>liftA2</hask>, etc, and <hask>ap</hask> with <hask>(<*>)</hask>. If your function signature was <hask>Monad m => ...</hask>, change to <hask>Applicative m => ...</hask> (and maybe rename <hask>m</hask> to <hask>f</hask> or whatever).<br />
<br />
== Alternative terms ==<br />
<br />
Applicative functors were introduced by several people under different names:<br />
* Ross Paterson called them [http://www.haskell.org/arrows/arrows/Control.Sequence.html Sequence]<br />
* Conor McBride called them [http://www.haskell.org/pipermail/haskell/2004-July/014315.html Idiom]<br />
* The same kind of structure is used in the [http://www.cs.uu.nl/wiki/Center/UtrechtParserCombinators UU Parsing-Combinators].<br />
<br />
<br />
== See also ==<br />
<br />
* [http://www.soi.city.ac.uk/~ross/papers/Applicative.html Applicative Programming with Effects]<br />
* The blog article [http://www.serpentine.com/blog/2008/02/06/the-basics-of-applicative-functors-put-to-practical-work/ The basics of applicative functors, put to practical work]</div>Turionhttps://wiki.haskell.org/index.php?title=Literate_programming&diff=62447Literate programming2018-04-22T17:40:22Z<p>Turion: Added minted package</p>
<hr />
<div>[[Category:Glossary]] [[Category:Tutorials]]<br />
Literate programming was invented / coined / started by [http://www-cs-faculty.stanford.edu/~knuth/ Dr. Donald Knuth]. In fact, if you asked Dr. Knuth what his favourite programming<br />
language was, (5th question of http://www-cs-faculty.stanford.edu/~knuth/faq.html) you would be told CWEB - which is a literate programming<br />
tool combining C and tex. <br />
<br />
What is literate programming? To quote Dr. Knuth: <br />
<blockquote>"The main idea is to regard a program as a communication to human beings rather than as a set of instructions to a computer."</blockquote><br />
<br />
The tool used to generate hyperlinked documentation from literate code is [[Haddock]]<br />
<br />
==Haskell and literate programming==<br />
Haskell is one of the few languages that provides native features to support literate programming. In haskell, a literate program is one with the suffix <code>.lhs</code> rather than <code>.hs</code>. <br />
<br />
In a literate Haskell program, there are two ways to distinguish between code and non-code portions. You can either prepend all code with a <code>&gt; </code>, (bird style) or surround lines of code with <code>\begin{code}</code> and <code>\end{code}</code> pairs (latex style). For those who know, use and love latex, the latter is the suggested way to go.<br />
<br />
Note that [[Happy]] supports literate programming as well, via bird style (the <code>&gt; </code> marker) in <code>.ly</code> files. Sadly, [[Alex]] no longer does. You might consider using [http://www.eecs.harvard.edu/~nr/noweb/ noweb] with it.<br />
<br />
==Bird Style==<br />
<br />
According to the [http://www.haskell.org/onlinereport/literate.html Haskell Report], this style of comment was developed by Richard Bird (hence the name) and Philip Wadler. All lines starting with <code>></code> are interpreted as code, everything else is considered a comment. One additional requirement is that you always leave a blank line before and after the code block:<br />
<br />
<haskell><br />
In Bird-style you have to leave a blank before the code.<br />
<br />
> fact :: Integer -> Integer<br />
> fact 0 = 1<br />
> fact n = n * fact (n-1)<br />
<br />
And you have to leave a blank line after the code as well.<br />
</haskell><br />
<br />
The idea behind this restriction is capturing the mistake of not inserting the <code>></code> mark at the beginning of the line. In general this is not only good practice, but also a formatting that makes the code more readable.<br />
<br />
However, there are cases in which you might like to get around this restriction. Perhaps you're writing Haskell code within a markup language that's not Latex, and you may have to surround your code with something equivalent to <code>\begin{code}</code> and <code>\end{code}</code>. In this case, GHC provides a flag that can be used to lift the blank lines requirement:<br />
<br />
<haskell><br />
$ ghc -optL -q<br />
</haskell><br />
<br />
<br />
==Latex suggestions for literate programming ==<br />
(See also [[#lhs2TeX]] below)<br />
In the majority of these suggestions, you can simply write:<br />
<br />
<haskell><br />
\begin{code}<br />
tsort [] = []<br />
tsort (x:xs) = tsort [y | y<-xs, y>x] ++ [x] ++ tsort [y | y<-xs, y<=x]<br />
\end{code}<br />
</haskell><br />
<br />
and the code will be formatted as you requested.<br />
<br />
The advantage: Source code and documentation are consistent! The code<br />
environment is understood by Haskell compilers, so you can run your<br />
documentation files directly.<br />
<br />
===Verbatim package===<br />
One can always simply use verbatim mode which will format the <br />
code "as-is".<br />
<br />
Use verbatim:<br />
<br />
<pre><br />
\usepackage{verbatim}<br />
\newenvironment{code}{\footnotesize\verbatim}{\endverbatim\normalsize}<br />
</pre><br />
===Listings package===<br />
Another alternative is to use the latex-package listings, which<br />
allows you to do much more customization of the output:<br />
<br />
<pre><br />
\usepackage{listings}<br />
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small}}{}<br />
</pre><br />
<br />
You can configure the appearance of the listings quite a bit! Some people find these settings to be the most satisfying:<br />
<br />
<pre><br />
\usepackage{listings}<br />
\lstloadlanguages{Haskell}<br />
\lstnewenvironment{code}<br />
{\lstset{}%<br />
\csname lst@SetFirstLabel\endcsname}<br />
{\csname lst@SaveFirstLabel\endcsname}<br />
\lstset{<br />
basicstyle=\small\ttfamily,<br />
flexiblecolumns=false,<br />
basewidth={0.5em,0.45em},<br />
literate={+}{{$+$}}1 {/}{{$/$}}1 {*}{{$*$}}1 {=}{{$=$}}1<br />
{>}{{$>$}}1 {<}{{$<$}}1 {\\}{{$\lambda$}}1<br />
{\\\\}{{\char`\\\char`\\}}1<br />
{->}{{$\rightarrow$}}2 {>=}{{$\geq$}}2 {<-}{{$\leftarrow$}}2<br />
{<=}{{$\leq$}}2 {=>}{{$\Rightarrow$}}2 <br />
{\ .}{{$\circ$}}2 {\ .\ }{{$\circ$}}2<br />
{>>}{{>>}}2 {>>=}{{>>=}}2<br />
{|}{{$\mid$}}1 <br />
}<br />
</pre><br />
<br />
You might want to consult the documentation of the "listings" package, to find out whether there's more you can tune to your likings. (Like adding line numbers, etc.) Note that the suggested "literate" option above will replace the given symbols anywhere in the text, including inside strings, which is probably not what one wants.<br />
<br />
For arrow notation add the line (requires MnSymbol package, or stmaryrd if you use Yleft instead):<br />
<pre><br />
{<<<}{{$\lll$}}2 {>>>}{{$\ggg$}}2 {-<}{{$\leftY$}}1<br />
</pre><br />
<br />
=== Minted package ===<br />
<br />
It is also possible to use the LaTeX package minted, which uses pygments for rich syntax highlighting:<br />
<pre><br />
\usepackage{minted}<br />
\newenvironment{code}{\VerbatimEnvironment\begin{minted}{haskell}}{\end{minted}}<br />
\newenvironment{spec}{\VerbatimEnvironment\begin{minted}{haskell}}{\end{minted}}<br />
</pre><br />
In order for LaTeX to be able to call pygments, you need to install pygments and call LaTeX with the <code>-shell-escape</code> flag.<br />
<br />
=== Hiding code from Latex ===<br />
<br />
If you want to hide some code, you can e.g. define:<br />
<br />
<pre><br />
\long\def\ignore#1{}<br />
</pre><br />
<br />
Auxiliary functions can be hidden as follows:<br />
<pre><br />
\ignore{<br />
\begin{code}<br />
help = putStr "Help me, what is this LiterateProgramming thing??"<br />
\end{code}<br />
}<br />
</pre><br />
Thanks to Wolfram Kahl, Oliver Braun and the people of the German TeX-newsgroup.<br />
<br />
Ciao,<br />
Steffen Mazanek<br />
<br />
http://www.steffen-mazanek.de<br />
<br />
=== Hiding code from Haskell ===<br />
<br />
If you want to hide a <code>\begin{code}...\end{code}</code> block from the ''compiler'', say, if you want to show an example in the text that is not actually part of the source code, you can just add a comment right after the "\begin{code}" statement. This will cause the Haskell parser to treat this block as text, not code:<br />
<br />
<pre><br />
And the definition of the following function<br />
would totally screw up my program, so I'm not<br />
definining it:<br />
<br />
\begin{code}% this is not really code<br />
main :: IO ()<br />
main = print "just an example"<br />
\end{code}<br />
<br />
See?<br />
</pre><br />
<br />
While this works well for vanilla LaTeX, if you're using lhs2TeX, then you'll get the "% this is not really code" printed in your output. Instead of doing the above, either use <code>\begin{spec} ... \end{spec}</code>, or if you're writing Bird-style code, flip your ">" characters around:<br />
<br />
<pre><br />
Neither of the following definitions are really code:<br />
<br />
\begin{spec}<br />
main :: IO ()<br />
main = print "another example"<br />
\end{spec}<br />
<br />
< main :: IO ()<br />
< main = print "...and another"<br />
<br />
</pre><br />
<br />
== Transformation of .lhs-files ==<br />
<br />
Sub-pages here have scripts to convert from the demarcation via <code>&gt; </code> (called "bird style" after Dr. Richard Bird) to <code>\begin{code}</code> and <code>\end{code}</code> pairs<br />
<br />
* [[Literate programming/Bird conversion via awk]]<br />
* [[Literate programming/Bird conversion via sed]]<br />
<br />
<br />
== Editors ==<br />
=== Multi-mode support in Emacs ===<br />
<br />
Another useful tool for literate programmers is the [http://mmm-mode.sourceforge.net/ mmm-mode] for Emacs. mmm-mode switches the current major mode of the buffer between two alternatives, depending on the context the cursor is in. If you're in, say, a <code>\begin{code}...\end{code}</code> block, you'll be editing in haskell-mode, but once you leave that block, you'll be editing in latex-mode.<br />
<br />
I have managed to cook up a configuration for both literate styles, but surely some Emacs guru can enhance these. To configure mmm-mode for Haskell, add these lines to your .emacs file:<br />
<br />
<pre><br />
(add-hook 'haskell-mode-hook 'my-mmm-mode)<br />
<br />
(mmm-add-classes<br />
'((literate-haskell-bird<br />
:submode text-mode<br />
:front "^[^>]"<br />
:include-front true<br />
:back "^>\\|$"<br />
)<br />
(literate-haskell-latex<br />
:submode literate-haskell-mode<br />
:front "^\\\\begin{code}"<br />
:front-offset (end-of-line 1)<br />
:back "^\\\\end{code}"<br />
:include-back nil<br />
:back-offset (beginning-of-line -1)<br />
)))<br />
<br />
(defun my-mmm-mode ()<br />
;; go into mmm minor mode when class is given<br />
(make-local-variable 'mmm-global-mode)<br />
(setq mmm-global-mode 'true))<br />
<br />
(setq mmm-submode-decoration-level 0)<br />
</pre><br />
<br />
You can activate mmm-mode by running "M-x mmm-ify-by-class" in the buffer. Emacs will prompt you for the class to use, to which should answer literate-haskell-bird or literate-haskell-latex, respectively.<br />
<br />
If you want Emacs to activate mmm-mode automatically for certain literate Haskell files, add these lines to it at the end:<br />
<br />
<pre><br />
% ----- Configure Emacs -----<br />
%<br />
% Local Variables: ***<br />
% mode: latex ***<br />
% mmm-classes: literate-haskell-latex ***<br />
% End: ***<br />
</pre><br />
<br />
This is, what the my-mmm-mode hook does, by the way.<br />
<br />
=== Vim ===<br />
<br />
See [[Literate programming/Vim]].<br />
<br />
== lhs2TeX ==<br />
<br />
Highly recommended is '''[https://hackage.haskell.org/package/lhs2tex lhs2TeX]''', courtesy of Andres Löh. It is designed for typesetting papers ''about'' Haskell, but '''lhs2TeX''' is easily configured and can make for a powerful preprocessor and documentation generator.<br />
<br />
Input to lhs2TeX is a slightly modified <code>.lhs</code> file. One would typically use the standard latex recommendations above, using a <code>\begin{code}</code> and <code>\end{code}</code> pair to demarcate code. Additionally, lhs2TeX provides specialized macros to control the preprocessing.<br />
<br />
Note that lhs2TeX and in-line commenting do not seem to mix well. <br />
<br />
Since it can typeset Haskell formulas in mathematical notation<br />
with LaTeX's math mode, you can also use it to create ''testable''<br />
papers. That is, readers can play with the formulas presented in the<br />
paper if they obtain the literate Haskell source code for the paper.<br />
<br />
== Shuffle ==<br />
<br />
[http://www.cs.uu.nl/wiki/Ehc/Shuffle Shuffle] is a tool which extends the capabilities of <code>lhs2TeX</code>. It was used in documenting the [http://www.cs.uu.nl/wiki/Ehc/WebHome Essential Haskell Compiler project]. It is available as part of this project, but it is usable also independently.<br />
<br />
==See also==<br />
* [http://www.literateprogramming.com/ Daniel Mall's website for Literate Programming.]<br />
* [http://en.wikipedia.org/wiki/Literate_programming Wikipedia]<br />
* [[Textual Haskell source]] - a <code>.ths</code> processor, where text is king.</div>Turionhttps://wiki.haskell.org/index.php?title=Literate_programming&diff=60853Literate programming2016-06-25T17:14:56Z<p>Turion: /* Listings package */ Spelling</p>
<hr />
<div>[[Category:Glossary]] [[Category:Tutorials]]<br />
Literate programming was invented / coined / started by [http://www-cs-faculty.stanford.edu/~knuth/ Dr. Donald Knuth]. In fact, if you asked Dr. Knuth what his favourite programming<br />
language was, (5th question of http://www-cs-faculty.stanford.edu/~knuth/faq.html) you would be told CWEB - which is a literate programming<br />
tool combining C and tex. <br />
<br />
What is literate programming? To quote Dr. Knuth: <br />
<blockquote>"The main idea is to regard a program as a communication to human beings rather than as a set of instructions to a computer."</blockquote><br />
<br />
The tool used to generate hyperlinked documentation from literate code is [[Haddock]]<br />
<br />
==Haskell and literate programming==<br />
Haskell is one of the few languages that provides native features to support literate programming. In haskell, a literate program is one with the suffix <code>.lhs</code> rather than <code>.hs</code>. <br />
<br />
In a literate Haskell program, there are two ways to distinguish between code and non-code portions. You can either prepend all code with a <code>&gt; </code>, (bird style) or surround lines of code with <code>\begin{code}</code> and <code>\end{code}</code> pairs (latex style). For those who know, use and love latex, the latter is the suggested way to go.<br />
<br />
Note that [[Happy]] supports literate programming as well, via bird style (the <code>&gt; </code> marker) in <code>.ly</code> files. Sadly, [[Alex]] no longer does. You might consider using [http://www.eecs.harvard.edu/~nr/noweb/ noweb] with it.<br />
<br />
==Bird Style==<br />
<br />
According to the [http://www.haskell.org/onlinereport/literate.html Haskell Report], this style of comment was developed by Richard Bird (hence the name) and Philip Wadler. All lines starting with <code>></code> are interpreted as code, everything else is considered a comment. One additional requirement is that you always leave a blank line before and after the code block:<br />
<br />
<haskell><br />
In Bird-style you have to leave a blank before the code.<br />
<br />
> fact :: Integer -> Integer<br />
> fact 0 = 1<br />
> fact n = n * fact (n-1)<br />
<br />
And you have to leave a blank line after the code as well.<br />
</haskell><br />
<br />
The idea behind this restriction is capturing the mistake of not inserting the <code>></code> mark at the beginning of the line. In general this is not only good practice, but also a formatting that makes the code more readable.<br />
<br />
However, there are cases in which you might like to get around this restriction. Perhaps you're writing Haskell code within a markup language that's not Latex, and you may have to surround your code with something equivalent to <code>\begin{code}</code> and <code>\end{code}</code>. In this case, GHC provides a flag that can be used to lift the blank lines requirement:<br />
<br />
<haskell><br />
$ ghc -optL -q<br />
</haskell><br />
<br />
<br />
==Latex suggestions for literate programming ==<br />
(See also [[#lhs2TeX]] below)<br />
In the majority of these suggestions, you can simply write:<br />
<br />
<haskell><br />
\begin{code}<br />
tsort [] = []<br />
tsort (x:xs) = tsort [y | y<-xs, y>x] ++ [x] ++ tsort [y | y<-xs, y<=x]<br />
\end{code}<br />
</haskell><br />
<br />
and the code will be formatted as you requested.<br />
<br />
The advantage: Source code and documentation are consistent! The code<br />
environment is understood by Haskell compilers, so you can run your<br />
documentation files directly.<br />
<br />
===Verbatim package===<br />
One can always simply use verbatim mode which will format the <br />
code "as-is".<br />
<br />
Use verbatim:<br />
<br />
<pre><br />
\usepackage{verbatim}<br />
\newenvironment{code}{\footnotesize\verbatim}{\endverbatim\normalsize}<br />
</pre><br />
===Listings package===<br />
Another alternative is to use the latex-package listings, which<br />
allows you to do much more customization of the output:<br />
<br />
<pre><br />
\usepackage{listings}<br />
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small}}{}<br />
</pre><br />
<br />
You can configure the appearance of the listings quite a bit! Some people find these settings to be the most satisfying:<br />
<br />
<pre><br />
\usepackage{listings}<br />
\lstloadlanguages{Haskell}<br />
\lstnewenvironment{code}<br />
{\lstset{}%<br />
\csname lst@SetFirstLabel\endcsname}<br />
{\csname lst@SaveFirstLabel\endcsname}<br />
\lstset{<br />
basicstyle=\small\ttfamily,<br />
flexiblecolumns=false,<br />
basewidth={0.5em,0.45em},<br />
literate={+}{{$+$}}1 {/}{{$/$}}1 {*}{{$*$}}1 {=}{{$=$}}1<br />
{>}{{$>$}}1 {<}{{$<$}}1 {\\}{{$\lambda$}}1<br />
{\\\\}{{\char`\\\char`\\}}1<br />
{->}{{$\rightarrow$}}2 {>=}{{$\geq$}}2 {<-}{{$\leftarrow$}}2<br />
{<=}{{$\leq$}}2 {=>}{{$\Rightarrow$}}2 <br />
{\ .}{{$\circ$}}2 {\ .\ }{{$\circ$}}2<br />
{>>}{{>>}}2 {>>=}{{>>=}}2<br />
{|}{{$\mid$}}1 <br />
}<br />
</pre><br />
<br />
You might want to consult the documentation of the "listings" package, to find out whether there's more you can tune to your likings. (Like adding line numbers, etc.) Note that the suggested "literate" option above will replace the given symbols anywhere in the text, including inside strings, which is probably not what one wants.<br />
<br />
For arrow notation add the line (requires MnSymbol package, or stmaryrd if you use Yleft instead):<br />
<pre><br />
{<<<}{{$\lll$}}2 {>>>}{{$\ggg$}}2 {-<}{{$\leftY$}}1<br />
</pre><br />
<br />
=== Hiding code from Latex ===<br />
<br />
If you want to hide some code, you can e.g. define:<br />
<br />
<pre><br />
\long\def\ignore#1{}<br />
</pre><br />
<br />
Auxiliary functions can be hidden as follows:<br />
<pre><br />
\ignore{<br />
\begin{code}<br />
help = putStr "Help me, what is this LiterateProgramming thing??"<br />
\end{code}<br />
}<br />
</pre><br />
Thanks to Wolfram Kahl, Oliver Braun and the people of the German TeX-newsgroup.<br />
<br />
Ciao,<br />
Steffen Mazanek<br />
<br />
http://www.steffen-mazanek.de<br />
<br />
=== Hiding code from Haskell ===<br />
<br />
If you want to hide a <code>\begin{code}...\end{code}</code> block from the ''compiler'', say, if you want to show an example in the text that is not actually part of the source code, you can just add a comment right after the "\begin{code}" statement. This will cause the Haskell parser to treat this block as text, not code:<br />
<br />
<pre><br />
And the definition of the following function<br />
would totally screw up my program, so I'm not<br />
definining it:<br />
<br />
\begin{code}% this is not really code<br />
main :: IO ()<br />
main = print "just an example"<br />
\end{code}<br />
<br />
See?<br />
</pre><br />
<br />
While this works well for vanilla LaTeX, if you're using lhs2TeX, then you'll get the "% this is not really code" printed in your output. Instead of doing the above, either use <code>\begin{spec} ... \end{spec}</code>, or if you're writing Bird-style code, flip your ">" characters around:<br />
<br />
<pre><br />
Neither of the following definitions are really code:<br />
<br />
\begin{spec}<br />
main :: IO ()<br />
main = print "another example"<br />
\end{spec}<br />
<br />
< main :: IO ()<br />
< main = print "...and another"<br />
<br />
</pre><br />
<br />
== Transformation of .lhs-files ==<br />
<br />
Sub-pages here have scripts to convert from the demarcation via <code>&gt; </code> (called "bird style" after Dr. Richard Bird) to <code>\begin{code}</code> and <code>\end{code}</code> pairs<br />
<br />
* [[Literate programming/Bird conversion via awk]]<br />
* [[Literate programming/Bird conversion via sed]]<br />
<br />
<br />
== Editors ==<br />
=== Multi-mode support in Emacs ===<br />
<br />
Another useful tool for literate programmers is the [http://mmm-mode.sourceforge.net/ mmm-mode] for Emacs. mmm-mode switches the current major mode of the buffer between two alternatives, depending on the context the cursor is in. If you're in, say, a <code>\begin{code}...\end{code}</code> block, you'll be editing in haskell-mode, but once you leave that block, you'll be editing in latex-mode.<br />
<br />
I have managed to cook up a configuration for both literate styles, but surely some Emacs guru can enhance these. To configure mmm-mode for Haskell, add these lines to your .emacs file:<br />
<br />
<pre><br />
(add-hook 'haskell-mode-hook 'my-mmm-mode)<br />
<br />
(mmm-add-classes<br />
'((literate-haskell-bird<br />
:submode text-mode<br />
:front "^[^>]"<br />
:include-front true<br />
:back "^>\\|$"<br />
)<br />
(literate-haskell-latex<br />
:submode literate-haskell-mode<br />
:front "^\\\\begin{code}"<br />
:front-offset (end-of-line 1)<br />
:back "^\\\\end{code}"<br />
:include-back nil<br />
:back-offset (beginning-of-line -1)<br />
)))<br />
<br />
(defun my-mmm-mode ()<br />
;; go into mmm minor mode when class is given<br />
(make-local-variable 'mmm-global-mode)<br />
(setq mmm-global-mode 'true))<br />
<br />
(setq mmm-submode-decoration-level 0)<br />
</pre><br />
<br />
You can activate mmm-mode by running "M-x mmm-ify-by-class" in the buffer. Emacs will prompt you for the class to use, to which should answer literate-haskell-bird or literate-haskell-latex, respectively.<br />
<br />
If you want Emacs to activate mmm-mode automatically for certain literate Haskell files, add these lines to it at the end:<br />
<br />
<pre><br />
% ----- Configure Emacs -----<br />
%<br />
% Local Variables: ***<br />
% mode: latex ***<br />
% mmm-classes: literate-haskell-latex ***<br />
% End: ***<br />
</pre><br />
<br />
This is, what the my-mmm-mode hook does, by the way.<br />
<br />
=== Vim ===<br />
<br />
See [[Literate programming/Vim]].<br />
<br />
== lhs2TeX ==<br />
<br />
Highly recommended is '''lhs2TeX''' at [http://www.cs.uu.nl/~andres/lhs2tex/], courtesy of Andres Löh. It is designed for typesetting papers ''about'' Haskell, but '''lhs2TeX''' is easily configured and can make for a powerful preprocessor and documentation generator.<br />
<br />
Input to lhs2TeX is a slightly modified <code>.lhs</code> file. One would typically use the standard latex recommendations above, using a <code>\begin{code}</code> and <code>\end{code}</code> pair to demarcate code. Additionally, lhs2TeX provides specialized macros to control the preprocessing.<br />
<br />
Note that lhs2TeX and in-line commenting do not seem to mix well. <br />
<br />
Since it can typeset Haskell formulas in mathematical notation<br />
with LaTeX's math mode, you can also use it to create ''testable''<br />
papers. That is, readers can play with the formulas presented in the<br />
paper if they obtain the literate Haskell source code for the paper.<br />
<br />
== Shuffle ==<br />
<br />
[http://www.cs.uu.nl/wiki/Ehc/Shuffle Shuffle] is a tool which extends the capabilities of <code>lhs2TeX</code>. It was used in documenting the [http://www.cs.uu.nl/wiki/Ehc/WebHome Essential Haskell Compiler project]. It is available as part of this project, but it is usable also independently.<br />
<br />
==See also==<br />
* [http://www.literateprogramming.com/ Daniel Mall's website for Literate Programming.]<br />
* [http://en.wikipedia.org/wiki/Literate_programming Wikipedia]<br />
* [[Textual Haskell source]] - a <code>.ths</code> processor, where text is king.</div>Turionhttps://wiki.haskell.org/index.php?title=Yampa/reactimate&diff=60820Yampa/reactimate2016-06-06T11:40:56Z<p>Turion: </p>
<hr />
<div><source lang="Haskell"><br />
reactimate :: IO a -- init<br />
-> (Bool -> IO (DTime, Maybe a)) -- input/sense<br />
-> (Bool -> b -> IO Bool) -- output/actuate<br />
-> SF a b -- process/signal function<br />
-> IO ()<br />
</source><br />
The <code>Bool</code> parameter of <code>sense</code> and <code>actuate</code> are unused if you look up the definition of reactimate so just ignore them (cf. the explanations below).<br />
<br />
<code>reactimate</code> basically is an input-process-output loop and forms the interface between (pure) Yampa signal functions and the (potentially impure) external world. More specifically, a Yampa signal function of type <code>SF a b</code> is an abstract data type that transforms a signal of type <code>Time -> a</code> into a signal of type <code>Time -> b</code> (note that one does not have direct access to signals in Yampa but just to signal functions). The <code>Time</code> parameter here is assumed to model continuous time but to evaluate a signal function (or a signal for that matter) it is necessary to sample the signals at discrete points in time. This is exactly what <code>reactimate</code> does (among other things).<br />
<br />
== Further explanations ==<br />
* The <code>init</code> action is rather self-explanatory; it executes an initial IO action (e.g. print a welcome message), which then yields an initial sample of type <code>a</code> for the signal function that is passed to <code>reactimate</code> as the last argument.<br />
* The <code>sense</code> argument is then evaluated at <code>False</code> and should return an IO action yielding a pair that contains the time passed since the last sample and a new sample of type <code>a</code> (wrapped in a <code>Maybe</code>) for the signal function. If the second component of <code>sense</code>'s return value is <code>Nothing</code> then the previous sample is used again.<br />
* <code>actuate</code> is evaluated at <code>True</code> and the signal function's output of type <code>b</code>, obtained by processing the input sample previously provided by <code>sense</code>. <code>actuate</code>'s job now is to process the output (e.g. render a collection of objects contained in it) in an IO action that yields a result of type <code>Bool</code>. If this result is <code>True</code> the processing loop stops (i.e. the IO action defined by <code>reactimate</code> returns <code>()</code>).<br />
* Finally, the last argument of <code>reactimate</code> is the signal function to be run (or "animated"). Keep in mind that the signal function may take pretty complex forms like a [[Yampa/Switches|parallel switch]] embedded in a loop.<br />
<br />
== Example ==<br />
To illustrate this, here's a simple example of a Hello World program but with some time dependence added. Its purpose is to print "Hello... wait for it..." to the console once and then wait for 2 seconds until it prints "World!" and then stops.<br />
<source lang="Haskell"><br />
import Control.Monad<br />
import Data.IORef<br />
import Data.Time.Clock<br />
import FRP.Yampa<br />
<br />
twoSecondsPassed :: SF () Bool<br />
twoSecondsPassed = time >>> arr (> 2)<br />
<br />
main :: IO ()<br />
main = do<br />
t <- getCurrentTime<br />
timeRef <- newIORef t<br />
reactimate initialize (sense timeRef) actuate twoSecondsPassed<br />
<br />
initialize :: IO ()<br />
initialize = putStrLn "Hello... wait for it..." <br />
<br />
actuate :: Bool -> Bool -> IO Bool<br />
actuate _ x = when x (putStrLn "World!") >> return x<br />
<br />
sense :: IORef UTCTime -> Bool -> IO (Double, Maybe ())<br />
sense timeRef _ = do<br />
now <- getCurrentTime<br />
lastTime <- readIORef timeRef<br />
writeIORef timeRef now<br />
let dt = now `diffUTCTime` lastTime<br />
return (realToFrac dt, Just ())<br />
</source><br />
<br />
Note that as soon as <code>x</code> in the definition of <code>actuate</code> becomes <code>True</code> (that is after 2 seconds), <code>actuate</code> returns <code>True</code>, hence reactimate returns <code>()</code> and the program stops. If we change the definition of <code>actuate</code> to always return <code>False</code> the line "World!" will be print out indefinitely.<br />
<br />
== Precision Issues ==<br />
In the above example, we used the standard <code>Data.Time.Clock</code> module to measure time differences. One should not use <code>System.CPUTime</code> because its precision is hardware dependent and can be very low. E.g. on a Core i7-2720QM, the precision is reduced by a factor of 10<sup>10</sup> compared to <code>Data.Time.Clock</code> (10ms vs. 1ps). This hardware dependence and potentially low precision make <code>System.CPUTime</code> unusable even for simple real time applications (like the game Pong) because the <code>integral</code> and <code>derivative</code> signal functions provided by Yampa behave unpredictably. This results in programs being highly system dependent; e.g. the ball in Pong moving significantly faster on faster hardware or even moving through a paddle because a collision is missed.</div>Turionhttps://wiki.haskell.org/index.php?title=Yampa/reactimate&diff=60819Yampa/reactimate2016-06-06T11:36:12Z<p>Turion: Improved code example</p>
<hr />
<div><source lang="Haskell"><br />
reactimate :: IO a -- init<br />
-> (Bool -> IO (DTime, Maybe a)) -- input/sense<br />
-> (Bool -> b -> IO Bool) -- output/actuate<br />
-> SF a b -- process/signal function<br />
-> IO ()<br />
</source><br />
The <code>Bool</code> parameter of <code>sense</code> and <code>actuate</code> are unused if you look up the definition of reactimate so just ignore them (cf. the explanations below).<br />
<br />
<code>reactimate</code> basically is an input-process-output loop and forms the interface between (pure) Yampa signal functions and the (potentially impure) external world. More specifically, a Yampa signal function of type <code>SF a b</code> is an abstract data type that transforms a signal of type <code>Time -> a</code> into a signal of type <code>Time -> b</code> (note that one does not have direct access to signals in Yampa but just to signal functions). The <code>Time</code> parameter here is assumed to model continuous time but to evaluate a signal function (or a signal for that matter) it is necessary to sample the signals at discrete points in time. This is exactly what <code>reactimate</code> does (among other things).<br />
<br />
== Further explanations ==<br />
* The <code>init</code> action is rather self-explanatory; it executes an initial IO action (e.g. print a welcome message), which then yields an initial sample of type <code>a</code> for the signal function that is passed to <code>reactimate</code> as the last argument.<br />
* The <code>sense</code> argument is then evaluated at <code>False</code> and should return an IO action yielding a pair that contains the time passed since the last sample and a new sample of type <code>a</code> (wrapped in a <code>Maybe</code>) for the signal function. If the second component of <code>sense</code>'s return value is <code>Nothing</code> then the previous sample is used again.<br />
* <code>actuate</code> is evaluated at <code>True</code> and the signal function's output of type <code>b</code>, obtained by processing the input sample previously provided by <code>sense</code>. <code>actuate</code>'s job now is to process the output (e.g. render a collection of objects contained in it) in an IO action that yields a result of type <code>Bool</code>. If this result is <code>True</code> the processing loop stops (i.e. the IO action defined by <code>reactimate</code> returns <code>()</code>).<br />
* Finally, the last argument of <code>reactimate</code> is the signal function to be run (or "animated"). Keep in mind that the signal function may take pretty complex forms like a [[Yampa/Switches|parallel switch]] embedded in a loop.<br />
<br />
== Example ==<br />
To illustrate this, here's a simple example of a Hello World program but with some time dependence added. Its purpose is to print "Hello... wait for it..." to the console once and then wait for 2 seconds until it prints "World!" and then stops.<br />
<source lang="Haskell"><br />
import Control.Monad<br />
import Data.IORef<br />
import Data.Time.Clock<br />
import FRP.Yampa<br />
<br />
twoSecondsPassed :: SF () Bool<br />
twoSecondsPassed = time >>> arr (> 2)<br />
<br />
main :: IO ()<br />
main = do<br />
t <- getCurrentTime<br />
timeRef <- newIORef t<br />
reactimate initialize (sense timeRef) actuate $ twoSecondsPassed<br />
<br />
initialize :: IO ()<br />
initialize = putStrLn "Hello... wait for it..." <br />
<br />
actuate :: Bool -> Bool -> IO Bool<br />
actuate _ x = when x (putStrLn "World!") >> return x<br />
<br />
sense :: IORef UTCTime -> Bool -> IO (Double, Maybe ())<br />
sense timeRef _ = do<br />
now <- getCurrentTime<br />
lastTime <- readIORef timeRef<br />
writeIORef timeRef now<br />
let dt = now `diffUTCTime` lastTime<br />
return (realToFrac dt, Just ())<br />
</source><br />
<br />
Note that as soon as <code>x</code> in the definition of <code>actuate</code> becomes <code>True</code> (that is after 2 seconds), <code>actuate</code> returns <code>True</code>, hence reactimate returns <code>()</code> and the program stops. If we change the definition of <code>actuate</code> to always return <code>False</code> the line "World!" will be print out indefinitely.<br />
<br />
== Precision Issues ==<br />
In the above example, we used the standard <code>Data.Time.Clock</code> module to measure time differences. One should not use <code>System.CPUTime</code> because its precision is hardware dependent and can be very low. E.g. on a Core i7-2720QM, the precision is reduced by a factor of 10<sup>10</sup> compared to <code>Data.Time.Clock</code> (10ms vs. 1ps). This hardware dependence and potentially low precision make <code>System.CPUTime</code> unusable even for simple real time applications (like the game Pong) because the <code>integral</code> and <code>derivative</code> signal functions provided by Yampa behave unpredictably. This results in programs being highly system dependent; e.g. the ball in Pong moving significantly faster on faster hardware or even moving through a paddle because a collision is missed.</div>Turionhttps://wiki.haskell.org/index.php?title=Yampa/reactimate&diff=60698Yampa/reactimate2016-04-26T13:28:45Z<p>Turion: /* Example */ Rename variables because of bug in wiki syntax highlighting</p>
<hr />
<div><source lang="Haskell"><br />
reactimate :: IO a -- init<br />
-> (Bool -> IO (DTime, Maybe a)) -- input/sense<br />
-> (Bool -> b -> IO Bool) -- output/actuate<br />
-> SF a b -- process/signal function<br />
-> IO ()<br />
</source><br />
The <code>Bool</code> parameter of <code>sense</code> and <code>actuate</code> are unused if you look up the definition of reactimate so just ignore them (cf. the explanations below).<br />
<br />
<code>reactimate</code> basically is an input-process-output loop and forms the interface between (pure) Yampa signal functions and the (potentially impure) external world. More specifically, a Yampa signal function of type <code>SF a b</code> is an abstract data type that transforms a signal of type <code>Time -> a</code> into a signal of type <code>Time -> b</code> (note that one does not have direct access to signals in Yampa but just to signal functions). The <code>Time</code> parameter here is assumed to model continuous time but to evaluate a signal function (or a signal for that matter) it is necessary to sample the signals at discrete points in time. This is exactly what <code>reactimate</code> does (among other things).<br />
<br />
== Further explanations ==<br />
* The <code>init</code> action is rather self-explanatory; it executes an initial IO action (e.g. print a welcome message), which then yields an initial sample of type <code>a</code> for the signal function that is passed to <code>reactimate</code> as the last argument.<br />
* The <code>sense</code> argument is then evaluated at <code>False</code> and should return an IO action yielding a pair that contains the time passed since the last sample and a new sample of type <code>a</code> (wrapped in a <code>Maybe</code>) for the signal function. If the second component of <code>sense</code>'s return value is <code>Nothing</code> then the previous sample is used again.<br />
* <code>actuate</code> is evaluated at <code>True</code> and the signal function's output of type <code>b</code>, obtained by processing the input sample previously provided by <code>sense</code>. <code>actuate</code>'s job now is to process the output (e.g. render a collection of objects contained in it) in an IO action that yields a result of type <code>Bool</code>. If this result is <code>True</code> the processing loop stops (i.e. the IO action defined by <code>reactimate</code> returns <code>()</code>).<br />
* Finally, the last argument of <code>reactimate</code> is the signal function to be run (or "animated"). Keep in mind that the signal function may take pretty complex forms like a [[Yampa/Switches|parallel switch]] embedded in a loop.<br />
<br />
== Example ==<br />
To illustrate this, here's a simple example of a Hello World program but with some time dependence added. Its purpose is to print "Hello... wait for it..." to the console once and then wait for 2 seconds until it prints "World!" and then stops.<br />
<source lang="Haskell"><br />
import Control.Monad<br />
import Data.IORef<br />
import Data.Time.Clock<br />
import FRP.Yampa<br />
<br />
twoSecondsPassed :: SF () Bool<br />
twoSecondsPassed = time >>> arr (> 2)<br />
<br />
main :: IO ()<br />
main = do<br />
t <- getCurrentTime<br />
timeRef <- newIORef t<br />
let init = putStrLn "Hello... wait for it..."<br />
actuate _ x = when x (putStrLn "World!") >> return x<br />
sense _ = do<br />
now <- getCurrentTime<br />
lastTime <- readIORef timeRef<br />
writeIORef timeRef now<br />
let dt = now `diffUTCTime` lastTime<br />
return (realToFrac dt, Just ())<br />
reactimate init sense actuate $ twoSecondsPassed<br />
</source><br />
<br />
Note that as soon as <code>x</code> in the definition of <code>actuate</code> becomes <code>True</code> (that is after 2 seconds), <code>actuate</code> returns <code>True</code>, hence reactimate returns <code>()</code> and the program stops. If we change the definition of <code>actuate</code> to always return <code>False</code> the line "World!" will be print out indefinitely.<br />
<br />
== Precision Issues ==<br />
In the above example, we used the standard <code>Data.Time.Clock</code> module to measure time differences. One should not use <code>System.CPUTime</code> because its precision is hardware dependent and can be very low. E.g. on a Core i7-2720QM, the precision is reduced by a factor of 10<sup>10</sup> compared to <code>Data.Time.Clock</code> (10ms vs. 1ps). This hardware dependence and potentially low precision make <code>System.CPUTime</code> unusable even for simple real time applications (like the game Pong) because the <code>integral</code> and <code>derivative</code> signal functions provided by Yampa behave unpredictably. This results in programs being highly system dependent; e.g. the ball in Pong moving significantly faster on faster hardware or even moving through a paddle because a collision is missed.</div>Turionhttps://wiki.haskell.org/index.php?title=Yampa/reactimate&diff=60697Yampa/reactimate2016-04-26T13:26:51Z<p>Turion: Replacing ugly code by acceptable code</p>
<hr />
<div><source lang="Haskell"><br />
reactimate :: IO a -- init<br />
-> (Bool -> IO (DTime, Maybe a)) -- input/sense<br />
-> (Bool -> b -> IO Bool) -- output/actuate<br />
-> SF a b -- process/signal function<br />
-> IO ()<br />
</source><br />
The <code>Bool</code> parameter of <code>sense</code> and <code>actuate</code> are unused if you look up the definition of reactimate so just ignore them (cf. the explanations below).<br />
<br />
<code>reactimate</code> basically is an input-process-output loop and forms the interface between (pure) Yampa signal functions and the (potentially impure) external world. More specifically, a Yampa signal function of type <code>SF a b</code> is an abstract data type that transforms a signal of type <code>Time -> a</code> into a signal of type <code>Time -> b</code> (note that one does not have direct access to signals in Yampa but just to signal functions). The <code>Time</code> parameter here is assumed to model continuous time but to evaluate a signal function (or a signal for that matter) it is necessary to sample the signals at discrete points in time. This is exactly what <code>reactimate</code> does (among other things).<br />
<br />
== Further explanations ==<br />
* The <code>init</code> action is rather self-explanatory; it executes an initial IO action (e.g. print a welcome message), which then yields an initial sample of type <code>a</code> for the signal function that is passed to <code>reactimate</code> as the last argument.<br />
* The <code>sense</code> argument is then evaluated at <code>False</code> and should return an IO action yielding a pair that contains the time passed since the last sample and a new sample of type <code>a</code> (wrapped in a <code>Maybe</code>) for the signal function. If the second component of <code>sense</code>'s return value is <code>Nothing</code> then the previous sample is used again.<br />
* <code>actuate</code> is evaluated at <code>True</code> and the signal function's output of type <code>b</code>, obtained by processing the input sample previously provided by <code>sense</code>. <code>actuate</code>'s job now is to process the output (e.g. render a collection of objects contained in it) in an IO action that yields a result of type <code>Bool</code>. If this result is <code>True</code> the processing loop stops (i.e. the IO action defined by <code>reactimate</code> returns <code>()</code>).<br />
* Finally, the last argument of <code>reactimate</code> is the signal function to be run (or "animated"). Keep in mind that the signal function may take pretty complex forms like a [[Yampa/Switches|parallel switch]] embedded in a loop.<br />
<br />
== Example ==<br />
To illustrate this, here's a simple example of a Hello World program but with some time dependence added. Its purpose is to print "Hello... wait for it..." to the console once and then wait for 2 seconds until it prints "World!" and then stops.<br />
<source lang="Haskell"><br />
import Control.Monad<br />
import Data.IORef<br />
import Data.Time.Clock<br />
import FRP.Yampa<br />
<br />
twoSecondsPassed :: SF () Bool<br />
twoSecondsPassed = time >>> arr (> 2)<br />
<br />
main :: IO ()<br />
main = do<br />
t <- getCurrentTime<br />
timeRef <- newIORef t<br />
let init = putStrLn "Hello... wait for it..."<br />
actuate _ x = when x (putStrLn "World!") >> return x<br />
sense _ = do<br />
t' <- getCurrentTime<br />
t <- readIORef timeRef<br />
writeIORef timeRef t'<br />
let dt = t' `diffUTCTime` t<br />
return (realToFrac dt, Just ())<br />
reactimate init sense actuate $ twoSecondsPassed<br />
</source><br />
<br />
Note that as soon as <code>x</code> in the definition of <code>actuate</code> becomes <code>True</code> (that is after 2 seconds), <code>actuate</code> returns <code>True</code>, hence reactimate returns <code>()</code> and the program stops. If we change the definition of <code>actuate</code> to always return <code>False</code> the line "World!" will be print out indefinitely.<br />
<br />
== Precision Issues ==<br />
In the above example, we used the standard <code>Data.Time.Clock</code> module to measure time differences. One should not use <code>System.CPUTime</code> because its precision is hardware dependent and can be very low. E.g. on a Core i7-2720QM, the precision is reduced by a factor of 10<sup>10</sup> compared to <code>Data.Time.Clock</code> (10ms vs. 1ps). This hardware dependence and potentially low precision make <code>System.CPUTime</code> unusable even for simple real time applications (like the game Pong) because the <code>integral</code> and <code>derivative</code> signal functions provided by Yampa behave unpredictably. This results in programs being highly system dependent; e.g. the ball in Pong moving significantly faster on faster hardware or even moving through a paddle because a collision is missed.</div>Turion