https://wiki.haskell.org/api.php?action=feedcontributions&user=Ertes&feedformat=atomHaskellWiki - User contributions [en]2022-01-20T16:54:10ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=Netwire&diff=57094Netwire2013-11-14T13:24:53Z<p>Ertes: /* Scope */ Expression.</p>
<hr />
<div>Netwire is a [[Functional Reactive Programming|functional reactive programming]] library that provides both an applicative and an arrow interface. It allows you to express time-varying values with a rich event system.<br />
<br />
* [http://hackage.haskell.org/package/netwire Project page]<br />
* [http://hub.darcs.net/ertes/netwire Source repository]<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* applicative interface (or optionally an arrow interface),<br />
* signal intervals,<br />
* dynamic switching,<br />
* rich set of predefined functionality,<br />
* signal analysis (average, interpolation, peak, etc.),<br />
* effectful reactive systems.<br />
<br />
== Scope ==<br />
<br />
Netwire's FRP framework is intended to be used for continuous applications. It replaces the traditional big main loop with its global state and event callbacks/branching by a completely declarative model. The following types of applications can benefit from using Netwire:<br />
<br />
* artificial intelligence and bots,<br />
* canvas-based graphics and animations,<br />
* continuous signal synthesis (audio waves, etc.),<br />
* games and game servers,<br />
* scene-based user interfaces (like OpenGL and vty),<br />
* simulations.<br />
<br />
If you can sensibly break your application down into ''frames'', then Netwire is for you. For other kinds of reactive applications like widget-based UIs you may want to look into [[reactive-banana]] instead.<br />
<br />
== Get started ==<br />
<br />
The documentation is contained within the package itself, but you can also read it online:<br />
<br />
* [http://hub.darcs.net/ertes/netwire/browse/README.md Tutorial]<br />
* [http://hackage.haskell.org/package/netwire Project page with API docs]<br />
<br />
== Model and correctness ==<br />
<br />
Netwire's underlying abstraction is more powerful than the [http://conal.net/papers/icfp97/ original formulation of time-varying values]. It allows you to implement general component systems with local state.<br />
<br />
Starting with Netwire 5 there are two module trees <hask>Control.Wire</hask> and <hask>FRP.Netwire</hask>. The latter exports a subset of Netwire that closely follows the original model and provides a set of predefined FRP wires.<br />
<br />
Signal intervals are an extension of the original model and an integral part of Netwire: A behavior is a ''partial'' function of time with the limitation that both the defined and undefined intervals must have a non-zero length. This extension makes it much easier to express switching and multicasting systems.<br />
<br />
== History ==<br />
<br />
This project started in 2011 as a replacement for Yampa to provide both a nicer interface and better integration into existing frameworks. Its original purpose was to power game servers and intelligent network bots. That's the origin of the name ''Netwire''.<br />
<br />
However, before its first release ''signal intervals'' were added (originally under the term ''signal inhibition''). Netwire became a completely new abstraction, so it lost its connection to Yampa.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=57093Netwire2013-11-14T13:23:14Z<p>Ertes: /* Scope */</p>
<hr />
<div>Netwire is a [[Functional Reactive Programming|functional reactive programming]] library that provides both an applicative and an arrow interface. It allows you to express time-varying values with a rich event system.<br />
<br />
* [http://hackage.haskell.org/package/netwire Project page]<br />
* [http://hub.darcs.net/ertes/netwire Source repository]<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* applicative interface (or optionally an arrow interface),<br />
* signal intervals,<br />
* dynamic switching,<br />
* rich set of predefined functionality,<br />
* signal analysis (average, interpolation, peak, etc.),<br />
* effectful reactive systems.<br />
<br />
== Scope ==<br />
<br />
Netwire's FRP framework is intended to be used for continuous applications. It replaces the usual big main loop with its global state and event callbacks/branching by a completely declarative model. The following types of applications can benefit from using Netwire:<br />
<br />
* artificial intelligence and bots,<br />
* canvas-based graphics and animations,<br />
* continuous signal synthesis (audio waves, etc.),<br />
* games and game servers,<br />
* scene-based user interfaces (like OpenGL and vty),<br />
* simulations.<br />
<br />
If you can sensibly break your application down into ''frames'', then Netwire is for you. For other kinds of reactive applications like widget-based UIs you may want to look into [[reactive-banana]] instead.<br />
<br />
== Get started ==<br />
<br />
The documentation is contained within the package itself, but you can also read it online:<br />
<br />
* [http://hub.darcs.net/ertes/netwire/browse/README.md Tutorial]<br />
* [http://hackage.haskell.org/package/netwire Project page with API docs]<br />
<br />
== Model and correctness ==<br />
<br />
Netwire's underlying abstraction is more powerful than the [http://conal.net/papers/icfp97/ original formulation of time-varying values]. It allows you to implement general component systems with local state.<br />
<br />
Starting with Netwire 5 there are two module trees <hask>Control.Wire</hask> and <hask>FRP.Netwire</hask>. The latter exports a subset of Netwire that closely follows the original model and provides a set of predefined FRP wires.<br />
<br />
Signal intervals are an extension of the original model and an integral part of Netwire: A behavior is a ''partial'' function of time with the limitation that both the defined and undefined intervals must have a non-zero length. This extension makes it much easier to express switching and multicasting systems.<br />
<br />
== History ==<br />
<br />
This project started in 2011 as a replacement for Yampa to provide both a nicer interface and better integration into existing frameworks. Its original purpose was to power game servers and intelligent network bots. That's the origin of the name ''Netwire''.<br />
<br />
However, before its first release ''signal intervals'' were added (originally under the term ''signal inhibition''). Netwire became a completely new abstraction, so it lost its connection to Yampa.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=57083Functional Reactive Programming2013-11-12T22:54:21Z<p>Ertes: /* People */ Added Ertugrul Söylemez.</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 />
* [http://hackage.haskell.org/package/sodium Sodium]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [[Netwire]]<br />
* [http://conal.net/fran/ Fran] (discontinued)<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
<br />
== Publications and talks ==<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 />
<br />
<br />
== Blog posts ==<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 />
<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://mcis.western.edu/~jpeterson/ John Peterson]<br />
* Ertugrul Söylemez<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=57082Netwire2013-11-12T20:47:44Z<p>Ertes: /* Scope */ Added remark about frames.</p>
<hr />
<div>Netwire is a [[Functional Reactive Programming|functional reactive programming]] library that provides both an applicative and an arrow interface. It allows you to express time-varying values with a rich event system.<br />
<br />
* [http://hackage.haskell.org/package/netwire Project page]<br />
* [http://hub.darcs.net/ertes/netwire Source repository]<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* applicative interface (or optionally an arrow interface),<br />
* signal intervals,<br />
* dynamic switching,<br />
* rich set of predefined functionality,<br />
* signal analysis (average, interpolation, peak, etc.),<br />
* effectful reactive systems.<br />
<br />
== Scope ==<br />
<br />
Netwire's FRP framework is intended to be used for continuous applications. It replaces the usual big main loop with its global state and event callbacks/branching by a completely declarative model. The following types of applications can benefit from using Netwire:<br />
<br />
* artificial intelligence and bots,<br />
* canvas-based graphics and animations,<br />
* games and game servers,<br />
* scene-based user interfaces (like OpenGL and vty),<br />
* simulations.<br />
<br />
If you can sensibly break your application down into ''frames'', then Netwire is for you. For other kinds of reactive applications like widget-based UIs you may want to look into [[reactive-banana]] instead.<br />
<br />
== Get started ==<br />
<br />
The documentation is contained within the package itself, but you can also read it online:<br />
<br />
* [http://hub.darcs.net/ertes/netwire/browse/README.md Tutorial]<br />
* [http://hackage.haskell.org/package/netwire Project page with API docs]<br />
<br />
== Model and correctness ==<br />
<br />
Netwire's underlying abstraction is more powerful than the [http://conal.net/papers/icfp97/ original formulation of time-varying values]. It allows you to implement general component systems with local state.<br />
<br />
Starting with Netwire 5 there are two module trees <hask>Control.Wire</hask> and <hask>FRP.Netwire</hask>. The latter exports a subset of Netwire that closely follows the original model and provides a set of predefined FRP wires.<br />
<br />
Signal intervals are an extension of the original model and an integral part of Netwire: A behavior is a ''partial'' function of time with the limitation that both the defined and undefined intervals must have a non-zero length. This extension makes it much easier to express switching and multicasting systems.<br />
<br />
== History ==<br />
<br />
This project started in 2011 as a replacement for Yampa to provide both a nicer interface and better integration into existing frameworks. Its original purpose was to power game servers and intelligent network bots. That's the origin of the name ''Netwire''.<br />
<br />
However, before its first release ''signal intervals'' were added (originally under the term ''signal inhibition''). Netwire became a completely new abstraction, so it lost its connection to Yampa.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=57081Functional Reactive Programming2013-11-12T17:00:20Z<p>Ertes: /* Behaviors */</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 />
* [http://hackage.haskell.org/package/sodium Sodium]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [[Netwire]]<br />
* [http://conal.net/fran/ Fran] (discontinued)<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
<br />
== Publications and talks ==<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 />
<br />
<br />
== Blog posts ==<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 />
<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://mcis.western.edu/~jpeterson/ John Peterson]<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=57080Functional Reactive Programming2013-11-12T16:50:59Z<p>Ertes: /* Introduction */ Removed Netwire-specific parts, replaced by generic introduction.</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 as well 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 />
* [http://hackage.haskell.org/package/sodium Sodium]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [[Netwire]]<br />
* [http://conal.net/fran/ Fran] (discontinued)<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
<br />
== Publications and talks ==<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 />
<br />
<br />
== Blog posts ==<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 />
<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://mcis.western.edu/~jpeterson/ John Peterson]<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=57079Netwire2013-11-12T15:38:00Z<p>Ertes: Netwire 5</p>
<hr />
<div>Netwire is a [[Functional Reactive Programming|functional reactive programming]] library that provides both an applicative and an arrow interface. It allows you to express time-varying values with a rich event system.<br />
<br />
* [http://hackage.haskell.org/package/netwire Project page]<br />
* [http://hub.darcs.net/ertes/netwire Source repository]<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* applicative interface (or optionally an arrow interface),<br />
* signal intervals,<br />
* dynamic switching,<br />
* rich set of predefined functionality,<br />
* signal analysis (average, interpolation, peak, etc.),<br />
* effectful reactive systems.<br />
<br />
== Scope ==<br />
<br />
Netwire's FRP framework is intended to be used for continuous applications. It replaces the usual big main loop with its global state and event callbacks/branching by a completely declarative model. The following types of applications can benefit from using Netwire:<br />
<br />
* artificial intelligence and bots,<br />
* canvas-based graphics and animations,<br />
* games and game servers,<br />
* scene-based user interfaces (like OpenGL and vty),<br />
* simulations.<br />
<br />
For other kinds of reactive applications like widget-based UIs you may want to look into [[reactive-banana]] instead.<br />
<br />
== Get started ==<br />
<br />
The documentation is contained within the package itself, but you can also read it online:<br />
<br />
* [http://hub.darcs.net/ertes/netwire/browse/README.md Tutorial]<br />
* [http://hackage.haskell.org/package/netwire Project page with API docs]<br />
<br />
== Model and correctness ==<br />
<br />
Netwire's underlying abstraction is more powerful than the [http://conal.net/papers/icfp97/ original formulation of time-varying values]. It allows you to implement general component systems with local state.<br />
<br />
Starting with Netwire 5 there are two module trees <hask>Control.Wire</hask> and <hask>FRP.Netwire</hask>. The latter exports a subset of Netwire that closely follows the original model and provides a set of predefined FRP wires.<br />
<br />
Signal intervals are an extension of the original model and an integral part of Netwire: A behavior is a ''partial'' function of time with the limitation that both the defined and undefined intervals must have a non-zero length. This extension makes it much easier to express switching and multicasting systems.<br />
<br />
== History ==<br />
<br />
This project started in 2011 as a replacement for Yampa to provide both a nicer interface and better integration into existing frameworks. Its original purpose was to power game servers and intelligent network bots. That's the origin of the name ''Netwire''.<br />
<br />
However, before its first release ''signal intervals'' were added (originally under the term ''signal inhibition''). Netwire became a completely new abstraction, so it lost its connection to Yampa.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=54675Functional Reactive Programming2012-11-16T16:24:37Z<p>Ertes: /* Introduction */ Netwire 4 is now on HackageDB.</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 />
FRP is about domain-specific languages that capture the notion of<br />
time-varying values. Let's take Netwire 4 as an example. You can install it either from HackageDB,<br />
<br />
cabal install netwire<br />
<br />
or by grabbing the latest source code via darcs:<br />
<br />
darcs get http://darcs.ertes.de/netwire/<br />
cd netwire<br />
cabal install<br />
<br />
Imagine you have a simple GUI label that displays the number of seconds<br />
passed since program start. In an event-based model this is actually<br />
quite a complicated task. You would have to create a label and update<br />
it all the time using some form of timer/idle event. In Netwire you<br />
write:<br />
<br />
myLabel = time<br />
<br />
Now let's say you want to have the same GUI, but the time should start<br />
at 10 and pass twice as fast, so you actually want to display twice the<br />
number of seconds passed plus 10:<br />
<br />
myLabel = 10 + 2*time<br />
<br />
Imagine you want to display the string "yes" in a label:<br />
<br />
myLabel = "yes"<br />
<br />
Now let's say you want to display "yes", when the space key is held down<br />
and "no" otherwise:<br />
<br />
myLabel = "yes" . keyDown Space <|> "no"<br />
<br />
You want to display time while pressed and "Press space" while not:<br />
<br />
myLabel = fmap show time . keyDown Space <|> "Press space"<br />
<br />
You want to display "yes" every other second and "no" otherwise:<br />
<br />
myLabel = "yes" . holdFor 1 (periodically 2) <|> "no"<br />
<br />
Imagine doing that with event-based code.<br />
<br />
Summary: FRP is about handling time-varying values like they were<br />
regular values.<br />
<br />
== Libraries ==<br />
* [http://hackage.haskell.org/package/sodium Sodium]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [[Netwire]]<br />
* [http://conal.net/fran/ Fran] (discontinued)<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
<br />
== Publications and talks ==<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 />
<br />
<br />
== Blog posts ==<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 />
<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://mcis.western.edu/~jpeterson/ John Peterson]<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43319Netwire2011-12-01T18:17:40Z<p>Ertes: /* Predefined wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Writing wires ==<br />
<br />
=== Predefined wires ===<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a ''stateful'' wire, because it changes over time:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
=== Composing wires ===<br />
<br />
The main feature of wires is that you can compose them using the arrow interface. There is a rich set of ways for composing, and you will want to use arrow notation for your convenience:<br />
<br />
<haskell><br />
system :: MyWire a String<br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
c2 <- countFrom 20 -< ()<br />
identity -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
In applications it is common to write wires that ignore their input. For those wires you should make the input type fully polymorphic to indicate this. Running this wire produces:<br />
<br />
<haskell><br />
stepWireM system ()<br />
<br />
1st instant: Right "10 20"<br />
2nd instant: Right "11 21"<br />
3rd instant: Right "12 22"<br />
</haskell><br />
<br />
Note: You can use the ''testWireM'' function with this wire. The following action will run the wire continuously printing its result at every 1000th instant:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return ()) system<br />
</haskell><br />
<br />
In the FRP context we often talk about ''signals''. Particularly in the context of ''arrowized'' FRP (AFRP) like Netwire we talk about ''signal networks'' and signals passing through them. The ''system'' wire is your first signal network. It ignores its input signal and passes the signal <hask>()</hask> to the two counters (which ignore their input signals, too). It takes the output signals <hask>c1</hask> and <hask>c2</hask> and makes a formatted string out of them. Finally this string is passed to the <hask>identity</hask> wire. This is the last wire in the signal network ''system'', so its output signal is the output signal of ''system''. As a side note the ''identity'' wire behaves like ''returnA''.<br />
<br />
The main feature to note here is that all of the subwires in the composition evolve individually. So in the second instant, each of the two counters will have gone up by one. This alone gives you a powerful abstraction for stateful computations. The equivalent when using a state monad or mutable variables would be to have a global state value with two counter values. By having time-varying functions you can have something called ''local state''. Each of the two counters (or as many as you use) have their own individual local state, which is the current counter value. This is way more convenient and composable than a state monad or other imperative state abstractions.<br />
<br />
=== Choice ===<br />
<br />
In traditional AFRP solutions like Yampa the path of a signal is fully determined by the structure of the signal network. In Netwire a signal can choose one of multiple paths by using the <hask>case</hask> and <hask>if</hask> constructs:<br />
<br />
<haskell><br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
if even c1<br />
then returnA -< "We don't want even c1"<br />
else do<br />
c2 <- countFrom 20 -< ()<br />
returnA -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
If the <hask>c1</hask> signal is even, then the wire outputs the string "We don't want even c1". Otherwise it takes the second path. Here it is important to know that the second counter will be suspended, when <hask>c1</hask> is even, because the <hask>else</hask> branch is not reached. A wire can only evolve, when it is actually reached. So in this example <hask>c2</hask> will run at half the speed of <hask>c1</hask> and the output will look like:<br />
<br />
<haskell><br />
1st instant: "We don't want even c1"<br />
2nd instant: "11 20"<br />
3rd instant: "We don't want even c1"<br />
4th instant: "13 21"<br />
5th instant: "We don't want even c1"<br />
6th instant: "15 22"<br />
7th instant: "We don't want even c1"<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43318Netwire2011-12-01T18:15:34Z<p>Ertes: /* Choice */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a ''stateful'' wire, because it changes over time:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
=== Composing wires ===<br />
<br />
The main feature of wires is that you can compose them using the arrow interface. There is a rich set of ways for composing, and you will want to use arrow notation for your convenience:<br />
<br />
<haskell><br />
system :: MyWire a String<br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
c2 <- countFrom 20 -< ()<br />
identity -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
In applications it is common to write wires that ignore their input. For those wires you should make the input type fully polymorphic to indicate this. Running this wire produces:<br />
<br />
<haskell><br />
stepWireM system ()<br />
<br />
1st instant: Right "10 20"<br />
2nd instant: Right "11 21"<br />
3rd instant: Right "12 22"<br />
</haskell><br />
<br />
Note: You can use the ''testWireM'' function with this wire. The following action will run the wire continuously printing its result at every 1000th instant:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return ()) system<br />
</haskell><br />
<br />
In the FRP context we often talk about ''signals''. Particularly in the context of ''arrowized'' FRP (AFRP) like Netwire we talk about ''signal networks'' and signals passing through them. The ''system'' wire is your first signal network. It ignores its input signal and passes the signal <hask>()</hask> to the two counters (which ignore their input signals, too). It takes the output signals <hask>c1</hask> and <hask>c2</hask> and makes a formatted string out of them. Finally this string is passed to the <hask>identity</hask> wire. This is the last wire in the signal network ''system'', so its output signal is the output signal of ''system''. As a side note the ''identity'' wire behaves like ''returnA''.<br />
<br />
The main feature to note here is that all of the subwires in the composition evolve individually. So in the second instant, each of the two counters will have gone up by one. This alone gives you a powerful abstraction for stateful computations. The equivalent when using a state monad or mutable variables would be to have a global state value with two counter values. By having time-varying functions you can have something called ''local state''. Each of the two counters (or as many as you use) have their own individual local state, which is the current counter value. This is way more convenient and composable than a state monad or other imperative state abstractions.<br />
<br />
=== Choice ===<br />
<br />
In traditional AFRP solutions like Yampa the path of a signal is fully determined by the structure of the signal network. In Netwire a signal can choose one of multiple paths by using the <hask>case</hask> and <hask>if</hask> constructs:<br />
<br />
<haskell><br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
if even c1<br />
then returnA -< "We don't want even c1"<br />
else do<br />
c2 <- countFrom 20 -< ()<br />
returnA -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
If the <hask>c1</hask> signal is even, then the wire outputs the string "We don't want even c1". Otherwise it takes the second path. Here it is important to know that the second counter will be suspended, when <hask>c1</hask> is even, because the <hask>else</hask> branch is not reached. A wire can only evolve, when it is actually reached. So in this example <hask>c2</hask> will run at half the speed of <hask>c1</hask> and the output will look like:<br />
<br />
<haskell><br />
1st instant: "We don't want even c1"<br />
2nd instant: "11 20"<br />
3rd instant: "We don't want even c1"<br />
4th instant: "13 21"<br />
5th instant: "We don't want even c1"<br />
6th instant: "15 22"<br />
7th instant: "We don't want even c1"<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43317Netwire2011-12-01T18:06:38Z<p>Ertes: /* Composing wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a ''stateful'' wire, because it changes over time:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
=== Composing wires ===<br />
<br />
The main feature of wires is that you can compose them using the arrow interface. There is a rich set of ways for composing, and you will want to use arrow notation for your convenience:<br />
<br />
<haskell><br />
system :: MyWire a String<br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
c2 <- countFrom 20 -< ()<br />
identity -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
In applications it is common to write wires that ignore their input. For those wires you should make the input type fully polymorphic to indicate this. Running this wire produces:<br />
<br />
<haskell><br />
stepWireM system ()<br />
<br />
1st instant: Right "10 20"<br />
2nd instant: Right "11 21"<br />
3rd instant: Right "12 22"<br />
</haskell><br />
<br />
Note: You can use the ''testWireM'' function with this wire. The following action will run the wire continuously printing its result at every 1000th instant:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return ()) system<br />
</haskell><br />
<br />
In the FRP context we often talk about ''signals''. Particularly in the context of ''arrowized'' FRP (AFRP) like Netwire we talk about ''signal networks'' and signals passing through them. The ''system'' wire is your first signal network. It ignores its input signal and passes the signal <hask>()</hask> to the two counters (which ignore their input signals, too). It takes the output signals <hask>c1</hask> and <hask>c2</hask> and makes a formatted string out of them. Finally this string is passed to the <hask>identity</hask> wire. This is the last wire in the signal network ''system'', so its output signal is the output signal of ''system''. As a side note the ''identity'' wire behaves like ''returnA''.<br />
<br />
The main feature to note here is that all of the subwires in the composition evolve individually. So in the second instant, each of the two counters will have gone up by one. This alone gives you a powerful abstraction for stateful computations. The equivalent when using a state monad or mutable variables would be to have a global state value with two counter values. By having time-varying functions you can have something called ''local state''. Each of the two counters (or as many as you use) have their own individual local state, which is the current counter value. This is way more convenient and composable than a state monad or other imperative state abstractions.<br />
<br />
=== Choice ===<br />
<br />
In traditional AFRP solutions like Yampa the path of a signal is fully determined by the structure of the signal network. In Netwire a signal can choose one of multiple paths by using the <hask>case</hask> and <hask>if</hask>:<br />
<br />
<haskell><br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
if even c1<br />
then returnA -< "We don't want even c1"<br />
else do<br />
c2 <- countFrom 20 -< ()<br />
returnA -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43316Netwire2011-12-01T17:59:22Z<p>Ertes: /* Composing wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a ''stateful'' wire, because it changes over time:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
=== Composing wires ===<br />
<br />
The main feature of wires is that you can compose them using the arrow interface. There is a rich set of ways for composing, and you will want to use arrow notation for your convenience:<br />
<br />
<haskell><br />
system :: MyWire a String<br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
c2 <- countFrom 20 -< ()<br />
identity -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
In applications it is common to write wires that ignore their input. For those wires you should make the input type fully polymorphic to indicate this. Running this wire produces:<br />
<br />
<haskell><br />
stepWireM system ()<br />
<br />
1st instant: Right "10 20"<br />
2nd instant: Right "11 21"<br />
3rd instant: Right "12 22"<br />
</haskell><br />
<br />
Note: You can use the ''testWireM'' function with this wire. The following action will run the wire continuously printing its result at every 1000th instant:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return ()) system<br />
</haskell><br />
<br />
In the FRP context we often talk about ''signals''. Particularly in the context of ''arrowized'' FRP (AFRP) like Netwire we talk about ''signal networks'' and signals passing through them. The ''system'' wire is your first signal network. It ignores its input signal and passes the signal <hask>()</hask> to the two counters (which ignore their input signals, too). It takes the output signals <hask>c1</hask> and <hask>c2</hask> and makes a formatted string out of them. Finally this string is passed to the <hask>identity</hask> wire. This is the last wire in the signal network ''system'', so its output signal is the output signal of ''system''. Side note: The ''identity'' wire behaves like ''returnA''.<br />
<br />
=== Choice ===<br />
<br />
In traditional AFRP solutions like Yampa the path of a signal is fully determined by the structure of the signal network. In Netwire a signal can choose one of multiple paths by using the <hask>case</hask> and <hask>if</hask>:<br />
<br />
<haskell><br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
if even c1<br />
then returnA -< "We don't want even c1"<br />
else do<br />
c2 <- countFrom 20 -< ()<br />
returnA -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43315Netwire2011-12-01T17:34:07Z<p>Ertes: /* Predefined wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a ''stateful'' wire, because it changes over time:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
=== Composing wires ===<br />
<br />
The main feature of wires is that you can compose them using the arrow interface. There is a rich set of ways for composing, and you will want to use arrow notation for your convenience:<br />
<br />
<haskell><br />
system :: MyWire a String<br />
system =<br />
proc _ -> do<br />
c1 <- countFrom 10 -< ()<br />
c2 <- countFrom 20 -< ()<br />
identity -< printf "%d %d" (c1 :: Int) (c2 :: Int)<br />
</haskell><br />
<br />
In applications it is common to write wires that ignore their input. For those wires you should make the input type fully polymorphic. Running this wire produces:<br />
<br />
<haskell><br />
1st instant: Right "10 20"<br />
2nd instant: Right "11 21"<br />
3rd instant: Right "12 22"<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43314Netwire2011-12-01T17:18:18Z<p>Ertes: /* Predefined wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
The ''countFrom'' function takes a starting value and returns a wire that returns sequential values instant by instant. This is the first example of a stateful wire:<br />
<br />
<haskell><br />
stepWireM (countFrom 15) inp<br />
-> (Right 15, countFrom 16)<br />
<br />
stepWireM (countFrom 16) inp<br />
-> (Right 16, countFrom 17)<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43313Netwire2011-12-01T17:07:35Z<p>Ertes: /* Predefined wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
Both identity and constant wires are examples of ''stateless'' wires. They don't change over time. You can see this in the stepping examples above. They always return themselves for the next instant.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43312Netwire2011-12-01T16:48:25Z<p>Ertes: Writing wires</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
<br />
== Predefined wires ==<br />
<br />
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):<br />
<br />
<haskell><br />
constant :: b -> Wire e (>~) a b<br />
identity :: Wire e (>~) b b<br />
countFrom :: Enum b => b -> Wire e (>~) a b<br />
</haskell><br />
<br />
The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again:<br />
<br />
<haskell><br />
stepWireM (constant 15) inp<br />
-> (Right 15, constant 15)<br />
</haskell><br />
<br />
Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored.<br />
<br />
The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant:<br />
<br />
<haskell><br />
stepWireM identity inp<br />
-> (Right inp, identity)<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43311Netwire2011-12-01T16:25:44Z<p>Ertes: /* Running wires */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.<br />
<br />
=== Testing wires ===<br />
<br />
There is a convenient function for testing wires, which does all the plumbing for you. It's called <hask>testWireM</hask>:<br />
<br />
<haskell><br />
testWireM ::<br />
(Show e, MonadIO m)<br />
=> Int<br />
-> m a<br />
-> Wire e (Kleisli m) a String<br />
-> m ()<br />
</haskell><br />
<br />
For wires returning a string, you can easily test them using this function. The first argument is a FPS/accuracy tradeoff. If it's 100, it will only print the output of every 100th instant. The second argument is an input generator action. At each instant, this action is run and its result is passed as input to the wire. The wire's output is then printed. <hask>testWireM</hask> prints the output continuously on a single line:<br />
<br />
<haskell><br />
main :: IO ()<br />
main = testWireM 1000 (return 15) system<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43310Netwire2011-12-01T16:00:13Z<p>Ertes: /* Basics */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>. You need to import the <hask>Control.Wire</hask> module to work with wires:<br />
<br />
<haskell><br />
import Control.Wire<br />
<br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because <hask>Wire</hask> is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== The inhibition monoid ===<br />
<br />
The <hask>e</hask> argument to <hask>Wire</hask> is called the inhibition monoid. For simple applications you can just use <hask>()</hask> here, but you may want to actually assign exception values to inhibition. We will cover that later. For now just use <hask>()</hask>.<br />
<br />
=== Base arrows ===<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow. In most cases you will use a <hask>Kleisli</hask> arrow here, and this is currently the only type of arrow supported, though more will be added in the future. For simple applications you can just use the <hask>IO</hask> monad, and it is useful to define a type alias for your custom wire type:<br />
<br />
<haskell><br />
type MyWire = Wire () (Kleisli IO)<br />
</haskell><br />
<br />
== Running wires ==<br />
<br />
For running a wire you can use the stepping functions available in the <hask>Control.Wire.Session</hask> module. There is no need to import that module. It is automatically imported with <hask>Control.Wire</hask>. For Kleisli-based wires you will want to use the <hask>stepWireM</hask> function:<br />
<br />
<haskell><br />
stepWireM ::<br />
Monad m<br />
=> Wire e (Kleisli m) a b<br />
-> a<br />
-> m (Either e b, Wire e (Kleisli m) a b)<br />
</haskell><br />
<br />
In our case we have <hask>m = IO</hask>, so our type signature is simply:<br />
<br />
<haskell><br />
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)<br />
</haskell><br />
<br />
This function takes a wire and an input value. It passes the input value to the wire and returns its result value of type <hask>Either () b</hask>. Along with the result it also returns a new wire. Normally you would call <hask>stepWireM</hask> in a loop, which performs instant after instant. This is the basic structure:<br />
<br />
<haskell><br />
system :: MyWire Int String<br />
system = {- ... -}<br />
<br />
main :: IO ()<br />
main = loop system<br />
where<br />
loop :: MyWire Int String -> IO ()<br />
loop w' = do<br />
(mx, w) <- stepWireM w' 15<br />
<br />
{- ... do something with mx ... -}<br />
<br />
loop w -- loop with the new wire.<br />
</haskell><br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=43308Netwire2011-12-01T15:17:59Z<p>Ertes: Updated to Netwire 3.0.0 – incomplete</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork and has many additional features.<br />
<br />
* [http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
This wiki page corresponds to Netwire version 3 and is currently a work in progress.<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of Netwire:<br />
<br />
* arrow interface (or optionally an applicative interface),<br />
* signal inhibition (ArrowZero / Alternative),<br />
* signal selection (ArrowPlus / Alternative),<br />
* self-adjusting wires (ArrowChoice),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* effectful wires.<br />
<br />
== Basics ==<br />
<br />
The Netwire library is based around a data type called <hask>Wire</hask>:<br />
<br />
<haskell><br />
data Wire e (>~) a b<br />
</haskell><br />
<br />
For some arrows <hask>(>~)</hask> and all monoids <hask>e</hask> the type <hask>Wire e (>~)</hask> is an arrow. Only certain arrows are allowed for <hask>(>~)</hask>, because ''Wire'' is actually a data family. These arrows are called base arrows in Netwire.<br />
<br />
<haskell><br />
comp :: Wire e (>~) a b<br />
</haskell><br />
<br />
Values of type <hask>Wire e (>~) a b</hask> are time-varying functions, which resemble the following type:<br />
<br />
<haskell><br />
a >~ Either e b<br />
</haskell><br />
<br />
So it's a function that takes a value of type <hask>a</hask> and either produces a value of type <hask>b</hask> or produces no value, but instead ''inhibits'' with a value of type <hask>e</hask>. The act of running a wire is called ''stepping'' and the process is called an ''instant''. You can step a wire through one of the stepping functions, which we will cover later. When you step a wire, it will return a new version of itself along with its result. You are supposed to call the new version the next time you step.<br />
<br />
=== Base arrows<br />
<br />
The <hask>(>~)</hask> argument to <hask>Wire</hask> is called the base arrow.<br />
<br />
[[Category:FRP]]</div>Erteshttps://wiki.haskell.org/index.php?title=Webwire&diff=42088Webwire2011-09-16T15:19:08Z<p>Ertes: </p>
<hr />
<div>== Examples ==<br />
<br />
As multiple people have asked for examples now, I'm providing some. Here is the obligatory Hello World application, which just displays a text/plain string:<br />
<br />
<haskell><br />
import Network.Wai.Handler.Warp<br />
import WebWire<br />
<br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -><br />
render -< "Hello world!" :: String<br />
</haskell><br />
<br />
Here is a slightly more interesting example showing how to use widgets:<br />
<br />
<haskell><br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -> do<br />
addWidget -< cssW "html { background: #aaa; }"<br />
addWidget -< bodyW (He.h1 (toHtml ("Hello world!" :: String)))<br />
renderDef -< ()<br />
</haskell><br />
<br />
Routing works through wire combination and signal inhibition. A wire can inhibit the output signal. This normally corresponds to a 404 error, though other errors are possible. Multiple wires can be combined. If one wire inhibits, the next is tried. If all wires inhibit, their sum inhibits. On its surface this is similar to how Happstack handles routing, but has a different underlying machinery. Also here I'm using Hamlet, Lucius and the 'time' wire to demonstrate how state is managed in this FRP-based framework:<br />
<br />
<haskell><br />
home :: WebWire site a Response<br />
home =<br />
rootDir $ proc _ -> do<br />
t <- time -< ()<br />
addWidget <<< cssLinkW ^<< pathAbs -< ["style", "test.css"]<br />
addWidget -< hamletW [hamlet|<br />
<h1>Hello world!<br />
<p>This server has been running for #{t} seconds.|]<br />
renderDef -< ()<br />
<br />
<br />
style :: WebWire site a Response<br />
style =<br />
directory "style" . file "test.css" $ proc _ -> do<br />
render -< [lucius| html { background: #aaa; } |] (\_ _ -> "")<br />
<br />
<br />
main :: IO ()<br />
main =<br />
let apps = style <+> home in<br />
simpleWire (run 4000) $ proc _ -> do<br />
setRoot -< ["http://localhost:4000"]<br />
apps -< ()<br />
</haskell><br />
<br />
For sessions you use the 'session' wire transformer. This is one of the most interesting features. The following website allows each session a maximum request rate of 10 requests per second:<br />
<br />
<haskell><br />
home :: WebWire site a Response<br />
home =<br />
rootDir $ proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 10 -< ()<br />
require_ -< fps <= 10<br />
<br />
fpsHi <- highPeak -< fps<br />
fpsLo <- lowPeak -< fps<br />
<br />
addWidget -< hamletW [hamlet|<br />
<h1>Hello world!<br />
<p>This session has been running for #{t} seconds.<br />
<p>Requests per second: #{fps} (high peak: #{fpsHi}) (low peak: #{fpsLo})|]<br />
renderDef -< ()<br />
<br />
<br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -> do<br />
setRoot -< ["http://localhost:4000"]<br />
session defSessionCfg home -< ()<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Webwire&diff=42087Webwire2011-09-16T15:18:29Z<p>Ertes: New page: Examples ======== As multiple people have asked for examples now, I'm providing some. Here is the obligatory Hello World application, which just displays a text/plain string: <haskell> ...</p>
<hr />
<div>Examples<br />
========<br />
<br />
As multiple people have asked for examples now, I'm providing some. Here is the obligatory Hello World application, which just displays a text/plain string:<br />
<br />
<haskell><br />
import Network.Wai.Handler.Warp<br />
import WebWire<br />
<br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -><br />
render -< "Hello world!" :: String<br />
</haskell><br />
<br />
Here is a slightly more interesting example showing how to use widgets:<br />
<br />
<haskell><br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -> do<br />
addWidget -< cssW "html { background: #aaa; }"<br />
addWidget -< bodyW (He.h1 (toHtml ("Hello world!" :: String)))<br />
renderDef -< ()<br />
</haskell><br />
<br />
Routing works through wire combination and signal inhibition. A wire can inhibit the output signal. This normally corresponds to a 404 error, though other errors are possible. Multiple wires can be combined. If one wire inhibits, the next is tried. If all wires inhibit, their sum inhibits. On its surface this is similar to how Happstack handles routing, but has a different underlying machinery. Also here I'm using Hamlet, Lucius and the 'time' wire to demonstrate how state is managed in this FRP-based framework:<br />
<br />
<haskell><br />
home :: WebWire site a Response<br />
home =<br />
rootDir $ proc _ -> do<br />
t <- time -< ()<br />
addWidget <<< cssLinkW ^<< pathAbs -< ["style", "test.css"]<br />
addWidget -< hamletW [hamlet|<br />
<h1>Hello world!<br />
<p>This server has been running for #{t} seconds.|]<br />
renderDef -< ()<br />
<br />
<br />
style :: WebWire site a Response<br />
style =<br />
directory "style" . file "test.css" $ proc _ -> do<br />
render -< [lucius| html { background: #aaa; } |] (\_ _ -> "")<br />
<br />
<br />
main :: IO ()<br />
main =<br />
let apps = style <+> home in<br />
simpleWire (run 4000) $ proc _ -> do<br />
setRoot -< ["http://localhost:4000"]<br />
apps -< ()<br />
</haskell><br />
<br />
For sessions you use the 'session' wire transformer. This is one of the most interesting features. The following website allows each session a maximum request rate of 10 requests per second:<br />
<br />
<haskell><br />
home :: WebWire site a Response<br />
home =<br />
rootDir $ proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 10 -< ()<br />
require_ -< fps <= 10<br />
<br />
fpsHi <- highPeak -< fps<br />
fpsLo <- lowPeak -< fps<br />
<br />
addWidget -< hamletW [hamlet|<br />
<h1>Hello world!<br />
<p>This session has been running for #{t} seconds.<br />
<p>Requests per second: #{fps} (high peak: #{fpsHi}) (low peak: #{fpsLo})|]<br />
renderDef -< ()<br />
<br />
<br />
main :: IO ()<br />
main =<br />
simpleWire (run 4000) $ proc _ -> do<br />
setRoot -< ["http://localhost:4000"]<br />
session defSessionCfg home -< ()<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41715Netwire2011-08-22T16:20:36Z<p>Ertes: Incompatibility notice.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
'''WARNING''': This wiki page corresponds to netwire version 1.0.0. The new version contains incompatible changes. I will update this page as soon as I have some spare time.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
withWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: NominalDiffTime -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of -0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which I provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and then returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41500Netwire2011-08-09T01:31:23Z<p>Ertes: /* Unique request numbers */ Typo.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
withWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of -0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which I provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and then returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41499Netwire2011-08-09T01:26:37Z<p>Ertes: /* Calculus */ Typo.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
withWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of -0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which I provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41498Netwire2011-08-09T01:25:59Z<p>Ertes: /* Calculus */ Typo.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
withWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of -0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41497Netwire2011-08-09T01:13:05Z<p>Ertes: /* Using a wire */ Typo.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
withWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41482Netwire2011-08-07T14:13:18Z<p>Ertes: /* Inhibiting */ Stupid typo.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained earlier. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41481Netwire2011-08-07T14:11:11Z<p>Ertes: Choice and signal inhibition</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.<br />
<br />
<br />
== Choice ==<br />
<br />
Wires can branch into multiple subwires, sending a signal to a subset of them. The easiest method to do that is using the ''ArrowChoice'' instance, which effectively enables you to use ''if'' and ''case'' inside of arrow notation:<br />
<br />
<haskell><br />
myWire :: Wire Double Double<br />
myWire =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 4<br />
then identity -< x<br />
else integral 0 -< 0.2<br />
</haskell><br />
<br />
This wire acts like the identity wire for four seconds and then switches into a clock, which starts at 0 and runs at 1/5 of the speed of time. The clock indeed starts at 0, because choice is exclusive. The wires, which have not been chosen are suspended. This effectively freezes their local time.<br />
<br />
Another method to perform choice is to use one of the parallel switches, which are explained in a later section.<br />
<br />
<br />
== Signal inhibition ==<br />
<br />
A wire may choose not to return anything, at which point it is said to be inhibiting. If the whole wire network inhibits, then the stepping functions will return ''Nothing''. If a wire in a sequence of wires inhibits, the later wires are not run.<br />
<br />
=== Inhibiting ===<br />
<br />
There are many ways to inhibit, the simplest being unconditional inhibition, which can be done with the ''inhibit'' wire:<br />
<br />
<haskell><br />
inhibit :: Wire a b<br />
</haskell><br />
<br />
This wire disregards its input and doesn't return. Note that ''inhibit'' is just a better name for the ''zeroArrow'' wire from the ''ArrowZero'' type class. You can use that one, if you prefer.<br />
<br />
In general you would prefer inhibition based on a predicate, for which there exist multiple ways. One simple way is to use ''inhibit'' together with choice:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
t <- time -< ()<br />
if t < 1 then inhibit -< ()<br />
else identity -< x<br />
</haskell><br />
<br />
This wire inhibits for one second and after that acts like the identity wire. Note that there is another way to write this wire using some of the predefined wires:<br />
<br />
<haskell><br />
waitOneSecond :: Wire a a<br />
waitOneSecond =<br />
proc x -> do<br />
ev <- after 1 -< ()<br />
swallow wait -< ev<br />
identity -< x<br />
</haskell><br />
<br />
The ''after'' wire was explained later. It will emit an event after one second. The ''wait'' wire extracts the event's value and returns it, unless no event happened, at which point it simply inhibits. However, the event occurs only once, so this would normally act like the identity wire for an instant and then return to inhibition. This is where ''swallow'' comes into play.<br />
<br />
<haskell><br />
swallow :: Wire a b -> Wire a b<br />
</haskell><br />
<br />
The ''swallow'' wire encapsulates the wire given as its argument and modifies its behaviour in the following way: As long as the inner wire inhibits, the ''swallow'' wire also inhibits, but as soon as the inner wire produces a result, ''swallow'' switches into the constant wire with that result. In other words, it waits for the first signal from the inner wire and then keeps that result forever.<br />
<br />
In this case ''wait'' would only produce a result once, but because it is wrapped by ''swallow'' this result is kept forever and the inner ''wait'' wire is dropped from the network.<br />
<br />
The ''swallow'' function is actually our first wire transformer. It takes a wire and encapsulates it modifying its behaviour.<br />
<br />
=== Combining ===<br />
<br />
You can combine two wires using the ''<+>'' combinator. This combinator comes from the ''ArrowPlus'' class and takes two wires as its argument. It passes the signal through the left wire. If that wire inhibits, it passes the signal to the right wire. The result of the first non-inhibiting wire is returned. If both wires inhibit, their combination inhibits.<br />
<br />
Note that if the first wire results, the second one is not run at all, thus ''<+>'' is left-biased. The following identities hold:<br />
<br />
<haskell><br />
w1 <+> inhibit = w1<br />
inhibit <+> w2 = w2<br />
</haskell><br />
<br />
=== Exhibition ===<br />
<br />
Sometimes you may want to observe inhibition. You can use the ''exhibit'' wire transformer for that purpose:<br />
<br />
<haskell><br />
exhibit :: Wire a b -> Wire a (Maybe b)<br />
</haskell><br />
<br />
It takes its argument wire and runs the input signal through it. If the inner wire inhibits, then ''exhibit'' returns ''Nothing''. It never inhibits. Thus the following identity holds:<br />
<br />
<haskell><br />
exhibit w1 <+> w2 = exhibit w1<br />
</haskell><br />
<br />
Note that this suggests correctly that signal inhibition can be interpreted as arrow exceptions, and ''exhibit'' acts like the ''try'' combinator.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41469Netwire2011-08-07T03:08:45Z<p>Ertes: /* Calculus */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vector space. Some examples of vector spaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41468Netwire2011-08-07T03:02:00Z<p>Ertes: /* Writing a wire */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vectorspace. Some examples of vectorspaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.<br />
<br />
=== Unique request numbers ===<br />
<br />
Sometimes you might want to generate numbers, which are unique throughout the wire session. For example you might want to manage game objects, open file handles or something similar. The ''identifier'' wire generates such unique numbers:<br />
<br />
<haskell><br />
identifier :: Wire a Int<br />
</haskell><br />
<br />
At the first instance it chooses a unique number and the returns that number forever.<br />
<br />
=== Impure wires ===<br />
<br />
As noted earlier wires are allowed to perform impure operations. There are three related utilities for this task:<br />
<br />
<haskell><br />
execute :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''execute'' wire is the simplest wire for impure operations. It takes an ''IO'' action as its input signal and outputs its result. If the action throws an exception, then this wire inhibits. Signal inhibition is explained in a later section.<br />
<br />
<haskell><br />
executeEvery :: Wire (DTime, IO a) a<br />
</haskell><br />
<br />
The ''executeEvery'' wire is useful for monitoring external resources. It takes two input signals. The right signal is an ''IO'' action, which is executed at intervals given by the left signal. The output is the most recent result of the action. This wire inhibits, until the action has returned a result for the first time. Note that ''executeEvery'' adheres to the interval, even if the action throws an exception.<br />
<br />
You may want to combine this wire with the ''diff'' wire to develop a wire, which reacts to changes.<br />
<br />
<haskell><br />
executeOnce :: Wire (IO a) a<br />
</haskell><br />
<br />
The ''executeOnce'' wire executes the action given by the input signal once at each instant, until it succeeds without an exception. The wire inhibits, until a result is available, at which point it returns that result forever without executing the action ever again.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41467Netwire2011-08-07T02:18:56Z<p>Ertes: /* Signal analysis */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vectorspace. Some examples of vectorspaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, if you pass the output of ''noise'' through ''avg x'' you should get a value close to 0.5, if the argument ''x'' is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell><br />
<br />
An interesting special case of ''avg'' is the ''avgFps'' wire, which is very useful for performance analysis. It returns the average frames per second:<br />
<br />
<haskell><br />
avgFps :: Int -> Wire a Double<br />
</haskell><br />
<br />
Both ''avg'' and ''avgFps'' calculate the average over a certain number of most recent samples. While they have a constant time complexity O(1) they have a linear space complexity of O(n), where ''n'' is the number of samples. In some cases it can be fine to consider calculating the average over all samples forever. The ''avgAll'' wire does exactly that:<br />
<br />
<haskell><br />
avgAll :: Wire Double Double<br />
</haskell><br />
<br />
Unlike ''avg'' and ''avgFps'' this variant uses not only constant time, but also constant space.<br />
<br />
There are also wires for finding peaks. The ''highPeak'' and ''lowPeak'' wires output the high and low peaks respectively for their input:<br />
<br />
<haskell><br />
highPeak :: (NFData a, Ord a) => Wire a a<br />
lowPeak :: (NFData a, Ord a) => Wire a a<br />
</haskell><br />
<br />
Again the type signatures are only special cases. See the library documentation for the real types. In short, you can get averages of any fractional input value.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41466Netwire2011-08-07T02:06:26Z<p>Ertes: /* Writing a wire */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
Time is measured in ''Double'' in Netwire. To improve type signatures there are two type aliases defined for you:<br />
<br />
<haskell><br />
type DTime = Double<br />
type Time = Double<br />
</haskell><br />
<br />
While ''Time'' refers to time, ''DTime'' refers to time deltas, i.e. time differences.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vectorspace. Some examples of vectorspaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.<br />
<br />
=== Events ===<br />
<br />
Events are a useful tool to add discrete values to the system. As the name states an event usually denotes some condition or external event, which can be present at some instants and absent at others. A common use case for events is user input.<br />
<br />
Technically events are nothing special. Since they simply denote values, which can be absent, they are simply ''Maybe'' values. Netwire defines a type alias ''Event'' to enable you to be more specific in your type signatures:<br />
<br />
<haskell><br />
type Event = Maybe<br />
</haskell><br />
<br />
There is a large number of event wires in the '''FRP.NetWire.Event''' module. I will give you examples for some of the common ones here. It is worthwhile to have a look at the aforementioned module.<br />
<br />
==== after ====<br />
<br />
<haskell><br />
after :: DTime -> Wire a (Event a)<br />
</haskell><br />
<br />
The ''after'' wire causes an event after a certain number of seconds. This means that the output signal is ''Nothing'', until the specified time has passed, at which point the output becomes ''Just x'' for a single instant, where ''x'' is the input value at that instant. After that the event never happens again.<br />
<br />
==== once ====<br />
<br />
<haskell><br />
once :: Wire (Event a) (Event a)<br />
</haskell><br />
<br />
This wire takes a potential event. It waits, until the event happens (i.e. the input becomes a ''Just''). It outputs the event once and then never again, even if the event happens again in the future.<br />
<br />
==== repeatedly ====<br />
<br />
<haskell><br />
repeatedly :: Wire (DTime, a) (Event a)<br />
</haskell><br />
<br />
This wire takes two input signals. It produces events repeatedly after the time delta given by the left signal. This delta can change over time, making the event happen more or less frequently. The right signal is the desired event value.<br />
<br />
==== hold ====<br />
<br />
<haskell><br />
hold :: a -> Wire (Event a) a<br />
</haskell><br />
<br />
This wire turns events into continuous signals. At the beginning the output is the value given by the argument. Each time the input event occurs, the ouput switches to its value and keeps it until the next event occurs.<br />
<br />
=== Random numbers ===<br />
<br />
Netwire provides a few wires for random noise generation. Probably the most important one is the ''noise'' wire:<br />
<br />
<haskell><br />
noise :: Wire a Double<br />
</haskell><br />
<br />
This wire outputs a random number between 0 (inclusive) and 1 (exclusive). The underlying random number generator is a fast implementation of the Mersenne Twister algorithm provided by Don Stewart's [http://hackage.haskell.org/package/mersenne-random mersenne-random] package.<br />
<br />
=== Signal analysis ===<br />
<br />
Netwire provides some wires to perform signal analysis. One useful wire is ''diff'':<br />
<br />
<haskell><br />
diff :: Eq a => Wire a (Event (a, Time))<br />
</haskell><br />
<br />
This wire emits an event, whenever the input signal changes. The event contains the last value as well as the time elapsed since then. One possible use case is file monitoring. Pass the file's modification time or even its contents as the input signal.<br />
<br />
Another useful wire is ''avg'', which computes the average value of the input signal over the specified number of most recent samples:<br />
<br />
<haskell><br />
avg :: Int -> Wire Double Double<br />
</haskell><br />
<br />
Since the ''noise'' wire returns random numbers between 0 and 1, you should get a value close to 0.5, if the argument is suitably large:<br />
<br />
<haskell><br />
avgOfNoise :: Wire a Double<br />
avgOfNoise = avg 1000 <<< noise<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41465Netwire2011-08-07T01:29:33Z<p>Ertes: Sections restructured.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
== Writing a wire ==<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
=== Time ===<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
=== Pure stateless wires ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
=== Pure stateful wires ===<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
=== Calculus ===<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vectorspace. Some examples of vectorspaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41464Netwire2011-08-07T01:28:11Z<p>Ertes: /* Calculus */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
=== Writing a wire ===<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
==== Calculus ====<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1. Here is the type of the ''integral'' wire, which integrates over time:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. The input is the subject of integration. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right towards positive infinity at first, while gradually becoming slower, until it reverses its direction and moves left towards negative infinity.<br />
<br />
The above type signature is actually a special case, which i provided for the sake of simplicity. The real type signature is a bit more interesting:<br />
<br />
<haskell><br />
integral ::<br />
(NFData v, VectorSpace v, Scalar v ~ Double) =><br />
v -> Wire v v<br />
</haskell><br />
<br />
You can integrate over time in any real vectorspace. Some examples of vectorspaces include tuples, complex numbers and any type, for which you define ''NFData'' and ''VectorSpace'' instances. Let's see the particle example in two dimensions:<br />
<br />
<haskell><br />
particle2D :: Wire a (Double, Double)<br />
particle2D =<br />
proc _ -> do<br />
v <- integral (1, -0.5) -< (-0.1, 0.4)<br />
integral (0, 0) -< v<br />
</haskell><br />
<br />
Differentiation works similarly, although there are two variants:<br />
<br />
<haskell><br />
derivative :: Wire Double Double<br />
derivativeFrom :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The difference between the two variants is that ''derivative'' will inhibit at the first instant (inhibition is explained later), because it needs at least two samples to compute the rate of change over time. The ''derivativeFrom'' variant does not have that shortcoming, but you need to provide the first sample as an argument.<br />
<br />
Again I have simplified the types to help understanding. Just like with integration you can differentiate over any vectorspace, as long as your type has an ''NFData'' instance.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41463Netwire2011-08-07T01:09:19Z<p>Ertes: Calculus</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
=== Writing a wire ===<br />
<br />
I will assume that you are familiar with arrow notation, and I will use it instead of the raw arrow combinators most of the time. If you haven't used arrow notation before, see the [http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html GHC arrow notation manual].<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
==== Calculus ====<br />
<br />
One of the compelling features of FRP is integration and differentiation over time. It is a very cheap operation to integrate over time. In fact the ''time'' wire you have seen in the last section is really just the integral of the constant 1:<br />
<br />
<haskell><br />
integral :: Double -> Wire Double Double<br />
</haskell><br />
<br />
The argument is the integration constant or starting value. Let's write a clock, which runs at half the speed of the real clock:<br />
<br />
<haskell><br />
slowClock :: Wire a Double<br />
slowClock = proc _ -> integral 0 -< 0.5<br />
</haskell><br />
<br />
Since the integration constant is 0, the time will start at zero. Integration becomes more interesting, as soon as you integrate non-constants:<br />
<br />
<haskell><br />
particle :: Wire a Double<br />
particle =<br />
proc _ -> do<br />
v <- integral 1 -< -0.1<br />
integral 15 -< v<br />
</haskell><br />
<br />
This wire models a one-dimensional particle, which starts at position 15 and velocity +1. A constant acceleration of 0.1 per second per second is applied to the velocity, hence the particle moves right at first, while gradually becoming slower, until it reverses its direction and moves towards negative infinity.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41462Netwire2011-08-07T00:47:20Z<p>Ertes: /* Using a wire */</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead. The ''stepWireDelta'' function takes a time delta, and the ''stepWireTime'' function takes the current time (which doesn't need to be the real time):<br />
<br />
<haskell><br />
stepWireDelta :: Double -> a -> Session a b -> IO (Maybe b)<br />
stepWireTime :: UTCTime -> a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
Note that it is allowed to give zero or negative deltas and times, which are earlier than the last time. This lets you run the system backwards in time. If you do that, your wire should be prepared to handle it properly.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same session from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
=== Writing a wire ===<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
'''TODO''': More to come.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41461Netwire2011-08-06T19:54:00Z<p>Ertes: Hackage link</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
:[http://hackage.haskell.org/package/netwire Download netwire]<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same wire from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
'''TODO''': More to come.</div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=41460Functional Reactive Programming2011-08-06T19:52:00Z<p>Ertes: /* Libraries */ Netwire wiki page.</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 />
== Libraries ==<br />
* [http://conal.net/fran/ Fran]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [[Netwire]]<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
== Material ==<br />
* [http://www.cs.rit.edu/~eca7215/frp-independent-study/Survey.pdf A Survey of Functional Reactive Programming] (PDF)<br />
* Conal Elliott’s FRP-related [http://conal.net/papers/frp.html papers] and [http://conal.net/blog/tag/functional-reactive-programming/ blog posts]<br />
* [[Grapefruit#Publications and talks|Grapefruit-related publications and talks]]<br />
* [http://haskell.cs.yale.edu/?page_id=65#FunctionalReactiveProgramming The Yale Haskell group’s latest publications] on functional reactive programming<br />
* [http://apfelmus.nfshost.com/blog.html#functional-reactive-programming-frp FRP section] of Heinrich Apfelmus' blog<br />
<br />
== People ==<br />
* [http://apfelmus.nfshost.com/ Heinrich Apfelmus]<br />
* [http://www.apocalypse.org/pub/u/antony/work/index.html Antony Courtney]<br />
* [http://conal.net/ Conal Elliott]<br />
* [http://sgate.emt.bme.hu/patai/ Patai Gergely]<br />
* [http://www.ittc.ku.edu/~andygill Andy Gill]<br />
* Liwen Huang<br />
* Paul Hudak<br />
* [http://www.tu-cottbus.de/fakultaet1/de/programmiersprachen-compilerbau/lehrstuhl/mitarbeiter/wolfgang-jeltsch.html Wolfgang Jeltsch]<br />
* [http://www.cs.nott.ac.uk/~nhn/ Henrik Nilsson]<br />
* [http://mcis.western.edu/~jpeterson/ John Peterson]<br />
<br />
== Blog articles ==<br />
* [http://lukepalmer.wordpress.com/2008/11/28/relative-time-frp/ Relative time FRP]<br />
* Several on [http://conal.net/blog Conal's blog]<br />
* [http://blog.edwardamsden.com/2011/03/demonstrating-time-leak-in-arrowized.html Demonstrating a Time Leak in Arrowized FRP]<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41459Netwire2011-08-06T19:51:10Z<p>Ertes: /* Pure stateful wires */ TODO notice.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same wire from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.<br />
<br />
'''TODO''': More to come.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41458Netwire2011-08-06T19:50:36Z<p>Ertes: /* Writing a wire */ A lot of changes.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same wire from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
==== Time ====<br />
<br />
To use this library you need to understand the concept of time very well. Netwire has a continuous time model, which means that when you write your applications you disregard the discrete steps, in which your wire is executed.<br />
<br />
Technically at each execution instant (i.e. each time you run ''stepWire'' or one of the other stepping functions) the wire is fed with the input as well as a time delta, which is the time passed since the last instant. Hence wires do not by themselves keep track of what time it is, since most applications don't need that anyway. If you need a clock, you can use the predefined ''time'' wire, which will be explained later.<br />
<br />
Wires have a local time, which can be different from the global time. This can happen, when a wire is not actually run, because an earlier wire inhibited the signal. It also happens, when you use choice. For example you can easily write a gateway, which repeatedly runs one wire the one second and another wire the other second. While one wire is run, the other wire is suspended, including its local time.<br />
<br />
Local time is a switching effect, which is especially visible, when you use the switching combinators from '''FRP.NetWire.Switch'''. Local time starts when switching in.<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input. The simplest wire is the ''identity'' wire. It just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.<br />
<br />
:'''Note''': You can express ''identity'' as ''arr id'', but you should prefer ''identity'', because it's faster. Likewise you can express ''constant x'' as ''arr (const x)'', but again you should prefer ''constant''.<br />
<br />
==== Pure stateful wires ====<br />
<br />
Let's see a slightly more interesting wire. The ''time'' wire will return the current local time. What ''local'' means in this context was explained earlier.<br />
<br />
<haskell><br />
time :: Wire a Double<br />
</haskell><br />
<br />
As the type suggests, time is measured in seconds and represented as a ''Double''. The local time starts from 0 at the point, where the wire starts to run. There is also a wire, which counts time from a different origin:<br />
<br />
<haskell><br />
timeFrom :: Double -> Wire a Double<br />
</haskell><br />
<br />
The difference between these stateful and the stateless wires from the previous section is that stateful wires mutate themselves over time. The ''timeFrom x'' wire calculates the current time as ''x'' plus the current time delta. Let's say that sum is ''y''. It then mutates into the wire ''timeFrom y''. As you can see there is no internal clock. It is really this self-mutation, which gives you a clock.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41457Netwire2011-08-06T18:59:44Z<p>Ertes: Typographic improvements and thread-safety notice</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (''ArrowZero'' / ''Alternative''),<br />
* choice and combination (''ArrowPlus'' / ''Alternative''),<br />
* self-adjusting wires (''ArrowChoice''),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of the '''FRP.NetWire.IO''' module, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator ''<+>''. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The ''w'' wire runs its signal through the wire ''w1'', and if it inhibits, it passes the signal to ''w2''.<br />
<br />
Another concept not found in Yampa is choice. Through the ''ArrowChoice'' instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write ''if'' and ''case'' constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an ''ArrowLoop'' instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the ''withWire'' and ''stepWire'' functions. The ''withWire'' initializes a wire and gives you a ''Session'' value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The ''stepWire'' function passes the given input value through the wire. If you use ''stepWire'', then the wire will mutate in real time. If you need a different rate of time, you can use ''stepWireDelta'' or ''stepWireTime'' instead.<br />
<br />
The stepping functions return a ''Maybe b''. If the wire inhibits, then the result is ''Nothing'', otherwise it will be ''Just'' the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
Note: Sessions are thread-safe. You are allowed to use the stepping functions for the same wire from multiple threads. This makes it easy to implement conditional stepping based on system events.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input and time. The simplest wire is the ''identity'' wire. It disregards time and just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41455Netwire2011-08-06T18:51:45Z<p>Ertes: Running example, pure stateless wires.</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (<code>ArrowZero</code> / <code>Alternative</code>),<br />
* choice and combination (<code>ArrowPlus</code> / <code>Alternative</code>),<br />
* self-adjusting wires (<code>ArrowChoice</code>),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of <code>FRP.NetWire.IO</code>, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator <code><+></code>. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The <code>w</code> wire runs its signal through the wire <code>w1</code>, and if it inhibits, it passes the signal to <code>w2</code>.<br />
<br />
Another concept not found in Yampa is choice. Through the <code>ArrowChoice</code> instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write <code>if</code> and <code>case</code> constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an <code>ArrowLoop</code> instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the <code>withWire</code> and <code>stepWire</code> functions. The <code>withWire</code> initializes a wire and gives you a <code>Session</code> value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The <code>stepWire</code> function passes the given input value through the wire. If you use <code>stepWire</code>, then the wire will mutate in real time. If you need a different rate of time, you can use <code>stepWireDelta</code> or <code>stepWireTime</code> instead.<br />
<br />
The stepping functions return a <code>Maybe b</code>. If the wire inhibits, then the result is <code>Nothing</code>, otherwise it will be <code>Just</code> the output. Here is a complete example:<br />
<br />
<haskell><br />
{-# LANGUAGE Arrows #-}<br />
<br />
module Main where<br />
<br />
import Control.Monad<br />
import FRP.NetWire<br />
import Text.Printf<br />
<br />
<br />
myWire :: Wire () String<br />
myWire =<br />
proc _ -> do<br />
t <- time -< ()<br />
fps <- avgFps 1000 -< ()<br />
fpsPeak <- highPeak -< fps<br />
<br />
if t < 4<br />
then identity -< "Waiting four seconds."<br />
else identity -<<br />
printf "Got them! (%8.0f FPS, peak: %8.0f)"<br />
fps fpsPeak<br />
<br />
<br />
main :: IO ()<br />
main = withWire myWire loop<br />
where<br />
loop :: Session () String -> IO ()<br />
loop session =<br />
forever $ do<br />
mResult <- stepWire () session<br />
case mResult of<br />
Nothing -> putStr "Signal inhibted."<br />
Just x -> putStr x<br />
putChar '\r'<br />
<br />
</haskell><br />
<br />
This program should display the string "Waiting four seconds." for four seconds and then switch to a string, which displays the current average frames per second and peak frames per second.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
==== Pure stateless wires ====<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input and time. The simplest wire is the ''identity'' wire. It disregards time and just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell><br />
<br />
If you run such a wire (see the previous section), then you will just get your input back all the time. Another simple wire is the ''constant'' wire, which also disregards time:<br />
<br />
<haskell><br />
constant :: b -> Wire a b<br />
</haskell><br />
<br />
If you run the wire <code>constant 15</code>, you will get as output the number 15 all the time, regardless of the current time and the input.</div>Erteshttps://wiki.haskell.org/index.php?title=Netwire&diff=41454Netwire2011-08-06T18:33:13Z<p>Ertes: Initial revision</p>
<hr />
<div>Netwire is a library for [[Functional Reactive Programming|functional reactive programming]], which uses the concept of [[Arrow|arrows]] for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with [[Yampa]] and its fork Animas, but it is itself not a fork.<br />
<br />
<br />
== Features ==<br />
<br />
Here is a list of some of the features of ''netwire'':<br />
<br />
* arrowized interface,<br />
* applicative interface,<br />
* signal inhibition (<code>ArrowZero</code> / <code>Alternative</code>),<br />
* choice and combination (<code>ArrowPlus</code> / <code>Alternative</code>),<br />
* self-adjusting wires (<code>ArrowChoice</code>),<br />
* rich set of event wires,<br />
* signal analysis wires (average, peak, etc.),<br />
* impure wires.<br />
<br />
== Quickstart ==<br />
<br />
This is a quickstart introduction to Netwire for Haskell programmers familiar with arrowized functional reactive programming (AFRP), for example Yampa or Animas. It should quickly give you an idea of how the library works and how it differs from the two mentioned.<br />
<br />
=== The wire ===<br />
<br />
Netwire calls its signal transformation functions ''wires''. You can think of a wire as a device with an input line and an output line. The difference between a function and a wire is that a wire can change itself throughout its lifetime. This is the basic idea of arrowized FRP. It gives you time-dependent values.<br />
<br />
A wire is parameterized over its input and output types:<br />
<br />
<haskell><br />
data Wire a b<br />
</haskell><br />
<br />
<br />
=== Differences from Yampa ===<br />
<br />
If you are not familiar with Yampa or Animas, you can safely skip this section.<br />
<br />
The main difference between Yampa and Netwire is that the underlying arrow is impure. While you can choose not to use the impure wires inside of <code>FRP.NetWire.IO</code>, it is a design choice for this library to explicitly allow impure computations. One theoretical implication is that you need to differentiate between pure stateless, pure stateful and impure signal transformations.<br />
<br />
A concept not found in Yampa is signal inhibition. A wire can choose not to return anything. This way you can temporarily block entire subnetworks. This is most useful with the combination operator <code><+></code>. Example:<br />
<br />
<haskell><br />
w = w1 <+> w2<br />
</haskell><br />
<br />
The <code>w</code> wire runs its signal through the wire <code>w1</code>, and if it inhibits, it passes the signal to <code>w2</code>.<br />
<br />
Another concept not found in Yampa is choice. Through the <code>ArrowChoice</code> instance wires allow you to choose one of a set of subwires for its signal without needing a switch. Essentially you can write <code>if</code> and <code>case</code> constructs inside of arrow notation.<br />
<br />
Because of their impurity wires do not have an <code>ArrowLoop</code> instance. It is possible to write one, but it will diverge most of the time, rendering it useless.<br />
<br />
<br />
=== Using a wire ===<br />
<br />
To run a wire you will need to use the <code>withWire</code> and <code>stepWire</code> functions. The <code>withWire</code> initializes a wire and gives you a <code>Session</code> value. As metioned earlier in general a wire is a function, which can mutate itself over time. The session value captures the current state of the wire.<br />
<br />
<haskell><br />
initWire :: Wire a b -> (Session a b -> IO c) -> IO c<br />
stepWire :: a -> Session a b -> IO (Maybe b)<br />
</haskell><br />
<br />
The <code>stepWire</code> function passes the given input value through the wire. If you use <code>stepWire</code>, then the wire will mutate in real time. If you need a different rate of time, you can use <code>stepWireDelta</code> or <code>stepWireTime</code> instead.<br />
<br />
The stepping functions return a <code>Maybe b</code>. If the wire inhibits, then the result is <code>Nothing</code>, otherwise it will be <code>Just</code> the output.<br />
<br />
<br />
=== Writing a wire ===<br />
<br />
Pure stateless wires are easy to explain, so let's start with them. A pure stateless wire is essentially just a function of input and time. The simplest wire is the ''identity'' wire. It disregards time and just returns its input verbatim:<br />
<br />
<haskell><br />
identity :: Wire a a<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Functional_Reactive_Programming&diff=41453Functional Reactive Programming2011-08-06T15:24:49Z<p>Ertes: /* Libraries */ Added the netwire package.</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 />
== Libraries ==<br />
* [http://conal.net/fran/ Fran]<br />
* [[Grapefruit]]<br />
* [[Reactive]]<br />
* [[DataDriven]]<br />
* [[Yampa]]<br />
* [[WxFruit|wxFruit]]<br />
* [http://hackage.haskell.org/package/elerea Elerea]<br />
* [[Reactive-banana|reactive-banana]]<br />
* [http://hackage.haskell.org/package/netwire Netwire]<br />
<br />
* [http://hackage.haskell.org/packages/archive/pkg-list.html#cat:frp Hackage packages in the category FRP]<br />
<br />
== Material ==<br />
* [http://www.cs.rit.edu/~eca7215/frp-independent-study/Survey.pdf A Survey of Functional Reactive Programming] (PDF)<br />
* Conal Elliott’s FRP-related [http://conal.net/papers/frp.html papers] and [http://conal.net/blog/tag/functional-reactive-programming/ blog posts]<br />
* [[Grapefruit#Publications and talks|Grapefruit-related publications and talks]]<br />
* [http://haskell.cs.yale.edu/?page_id=65#FunctionalReactiveProgramming The Yale Haskell group’s latest publications] on functional reactive programming<br />
* [http://apfelmus.nfshost.com/blog.html#functional-reactive-programming-frp FRP section] of Heinrich Apfelmus' blog<br />
<br />
== People ==<br />
* [http://apfelmus.nfshost.com/ Heinrich Apfelmus]<br />
* [http://www.apocalypse.org/pub/u/antony/work/index.html Antony Courtney]<br />
* [http://conal.net/ Conal Elliott]<br />
* [http://sgate.emt.bme.hu/patai/ Patai Gergely]<br />
* [http://www.ittc.ku.edu/~andygill Andy Gill]<br />
* Liwen Huang<br />
* Paul Hudak<br />
* [http://www.tu-cottbus.de/fakultaet1/de/programmiersprachen-compilerbau/lehrstuhl/mitarbeiter/wolfgang-jeltsch.html Wolfgang Jeltsch]<br />
* [http://www.cs.nott.ac.uk/~nhn/ Henrik Nilsson]<br />
* [http://mcis.western.edu/~jpeterson/ John Peterson]<br />
<br />
== Blog articles ==<br />
* [http://lukepalmer.wordpress.com/2008/11/28/relative-time-frp/ Relative time FRP]<br />
* Several on [http://conal.net/blog Conal's blog]<br />
* [http://blog.edwardamsden.com/2011/03/demonstrating-time-leak-in-arrowized.html Demonstrating a Time Leak in Arrowized FRP]<br />
<br />
[[Category:FRP|*]]</div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36901Contstuff2010-10-01T02:50:56Z<p>Ertes: /* Lifting */ Adjusted to recent changes in the library.</p>
<hr />
<div>The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The ''ContT'' monad transformer is the simplest of all CPS-based monads:<br />
<br />
<haskell><br />
newtype ContT r m a<br />
</haskell><br />
<br />
It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ''ContT'' you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of ''ContT''. If you don't use them, then ''ContT'' behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a ''ContT'' computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of ''ContT''. First of all, ''ContT'' is a monad transformer, so you can for example lift ''IO'' actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the ''IO'' monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to ''ContT''.<br />
<br />
Each ''ContT'' subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m ()<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in ''contstuff''. This means you can carry them around. They are only limited in that they can't be carried outside of a ''ContT'' computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: LiftBase m => Base m a -> m a<br />
io :: (LiftBase m, Base m ~ IO) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to ''IO''.<br />
<br />
=== Accumulating results ===<br />
<br />
''ContT'' does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
== State ==<br />
<br />
The ''contstuff'' library also comes with a monad transformer for stateful computations. These computations carry state of a certain type and can access it at any time. It's called ''StateT'', just like in other transformer libraries, but this one has very different semantics and also takes an additional parameter:<br />
<br />
<haskell><br />
newtype StateT r s m a<br />
</haskell><br />
<br />
It is basically a generalization of ''ContT''. In fact you can use all the features of ''ContT'' in a ''StateT'' computation, too, including abortion, labels, accumulation, etc.<br />
<br />
The <hask>r</hask> parameter is the type of the final result. In actual computations this parameter can be left polymorphic most of the time, unless you use abortion.<br />
<br />
=== Accessing the state ===<br />
<br />
There are many functions to access the implicit state. These don't belong to ''StateT'' directly, but instead to a type class called ''Stateful'', of which ''StateT'' is an instance. The associated type <hask>StateOf m</hask> is the type of the state of the monad <hask>m</hask>:<br />
<br />
<haskell><br />
-- Where 'm' is a Stateful monad, 'StateOf m' is the type of its state.<br />
get :: (Stateful m) => m (StateOf m)<br />
put :: (Stateful m) => StateOf m -> m ()<br />
putLazy :: (Stateful m) => StateOf m -> m ()<br />
<br />
-- Convenience functions.<br />
getField :: (Functor m, Stateful m) => (StateOf m -> a) -> m a<br />
modify :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyLazy :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyField :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
modifyFieldLazy :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
</haskell><br />
<br />
As the names suggest ''StateT'' is strict by default. When setting a new state using <hask>put</hask>, the state is evaluated. If you want to avoid that use <hask>putLazy</hask> instead.<br />
<br />
=== Running ===<br />
<br />
To run a stateful computation you can use the <hask>runStateT</hask> function, which takes a final continuation, an initial state and a stateful computation as arguments. There are two convenience functions <hask>evalStateT</hask><br />
<br />
<haskell><br />
runStateT :: s -> (s -> a -> m r) -> StateT r s m a -> m r<br />
evalStateT :: (Applicative m) => s -> StateT r s m r -> m r<br />
execStateT :: (Applicative m) => s -> StateT s s m a -> m s<br />
</haskell><br />
<br />
In most cases you will just use <hask>evalStateT</hask> or <hask>execStateT</hask>.<br />
<br />
== Exceptions ==<br />
<br />
''Contstuff'' provides an ''EitherT'' monad transformer:<br />
<br />
<haskell><br />
newtype EitherT r e m a<br />
</haskell><br />
<br />
This monad transformer is a generalization of ''ContT'' in that it supports two continuations. The second one can be accessed indirectly by the various exception handling functions.<br />
<br />
=== Raising and catching ===<br />
<br />
There are a number of functions to handle exceptions, which belong to a class <hask>HasExceptions</hask> with an associated type <hask>Exception m</hask>. ''EitherT'' is an instance of this class.<br />
<br />
<haskell><br />
-- Where 'm' is a monad supporting exceptions, 'Exception m' is the<br />
-- type of the exceptions.<br />
raise :: (HasExceptions m) => Exception m -> m a<br />
try :: (HasExceptions m) => m a -> m (Either (Exception m) a)<br />
<br />
-- Convenience functions.<br />
catch :: (HasExceptions m, Monad m) => m a -> (Exception m -> m a) -> m a<br />
handle :: (HasExceptions m, Monad m) => (Exception m -> m a) -> m a -> m a<br />
finally :: (HasExceptions m, Monad m) => m a -> m b -> m a<br />
bracket :: (HasExceptions m, Monad m) =><br />
m res -> (res -> m b) -> (res -> m a) -> m a<br />
bracket_ :: (HasExceptions m, Monad m) => m a -> m b -> m c -> m c<br />
</haskell><br />
<br />
Please note that <hask>bracket</hask> and <hask>bracket_</hask> have slightly different semantics than the corresponding functions from <hask>Control.Exception</hask>. If an exception is raised in both the middle computation and the final computation, then the middle one is significant.<br />
<br />
=== Running ===<br />
<br />
To run an ''EitherT'' computation you can use the <hask>runEitherT</hask> function, which expects the two final continuations and an ''EitherT'' computation. There is also a convenience function <hask>evalEitherT</hask>, which just returns an ''Either'' value:<br />
<br />
<haskell><br />
runEitherT :: (a -> m r) -> (e -> m r) -> EitherT r e m a -> m r<br />
evalEitherT :: (Applicative m) =><br />
EitherT (Either e a) e m a -> m (Either e a)<br />
</haskell><br />
<br />
== Choice/nondeterminism ==<br />
<br />
The ''ChoiceT'' monad transformer is basically a list monad transformer and a proper one at that. It is also very fast, because choice is implemented as a CPS-based left fold function:<br />
<br />
<haskell><br />
newtype ChoiceT r i m a<br />
</haskell><br />
<br />
The parameters <hask>r</hask> and <hask>i</hask> are the types of the final and the intermediate results respectively. In actual computations, unless you use abortion, these can be left polymorphic most of the time. Also practically they are almost always the same. Don't worry about them.<br />
<br />
=== Running ===<br />
<br />
You can run a ''ChoiceT'' computation by using the slightly scary <hask>runChoiceT</hask> function:<br />
<br />
<haskell><br />
runChoiceT ::<br />
(i -> a -> (i -> m r) -> m r) -> i -> (i -> m r)<br />
-> ChoiceT r i m a -> m r<br />
</haskell><br />
<br />
This function takes a folding function, a base element, a final continuation (the folding function uses CPS) and a ''ChoiceT'' computation. Of course in practice you mostly just want a list of results or the first result or something like that. Luckily there are two convenience functions to do just that:<br />
<br />
<haskell><br />
findFirst :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
findAll :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
</haskell><br />
<br />
Even these look scary, but they really aren't. In most cases <hask>f</hask> is just <hask>[]</hask> or <hask>Maybe</hask>. But there are more convenience functions:<br />
<br />
<haskell><br />
maybeChoiceT :: Applicative m =><br />
ChoiceT (Maybe a) (Maybe a) m a -> m (Maybe a)<br />
listChoiceT :: Applicative m => ChoiceT [a] [a] m a -> m [a]<br />
</haskell><br />
<br />
The <hask>maybeChoiceT</hask> function is just a special case of <hask>findFirst</hask>. The <hask>listChoiceT</hask> in contrast does not behave like <hask>findAll</hask>. It returns the results in reversed order and is much faster than <hask>findAll</hask>.<br />
<br />
=== Convenience functions ===<br />
<br />
Often you just want to encode a list of choices. For this you can use the <hask>listA</hask> function discussed earlier:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
There is an alternative function, which works only for ''ChoiceT'', but is much faster than <hask>listA</hask>, called just <hask>choice</hask>:<br />
<br />
<haskell><br />
choice :: [a] -> ChoiceT r i m a<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36898Contstuff2010-09-30T02:18:03Z<p>Ertes: /* Resumption and branches */ Corrected type of 'goto'</p>
<hr />
<div>The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The ''ContT'' monad transformer is the simplest of all CPS-based monads:<br />
<br />
<haskell><br />
newtype ContT r m a<br />
</haskell><br />
<br />
It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ''ContT'' you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of ''ContT''. If you don't use them, then ''ContT'' behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a ''ContT'' computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of ''ContT''. First of all, ''ContT'' is a monad transformer, so you can for example lift ''IO'' actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the ''IO'' monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to ''ContT''.<br />
<br />
Each ''ContT'' subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m ()<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in ''contstuff''. This means you can carry them around. They are only limited in that they can't be carried outside of a ''ContT'' computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: (LiftBase m a) => Base m a -> m a<br />
io :: (Base m a ~ IO a, LiftBase m a) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to ''IO''.<br />
<br />
=== Accumulating results ===<br />
<br />
''ContT'' does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
== State ==<br />
<br />
The ''contstuff'' library also comes with a monad transformer for stateful computations. These computations carry state of a certain type and can access it at any time. It's called ''StateT'', just like in other transformer libraries, but this one has very different semantics and also takes an additional parameter:<br />
<br />
<haskell><br />
newtype StateT r s m a<br />
</haskell><br />
<br />
It is basically a generalization of ''ContT''. In fact you can use all the features of ''ContT'' in a ''StateT'' computation, too, including abortion, labels, accumulation, etc.<br />
<br />
The <hask>r</hask> parameter is the type of the final result. In actual computations this parameter can be left polymorphic most of the time, unless you use abortion.<br />
<br />
=== Accessing the state ===<br />
<br />
There are many functions to access the implicit state. These don't belong to ''StateT'' directly, but instead to a type class called ''Stateful'', of which ''StateT'' is an instance. The associated type <hask>StateOf m</hask> is the type of the state of the monad <hask>m</hask>:<br />
<br />
<haskell><br />
-- Where 'm' is a Stateful monad, 'StateOf m' is the type of its state.<br />
get :: (Stateful m) => m (StateOf m)<br />
put :: (Stateful m) => StateOf m -> m ()<br />
putLazy :: (Stateful m) => StateOf m -> m ()<br />
<br />
-- Convenience functions.<br />
getField :: (Functor m, Stateful m) => (StateOf m -> a) -> m a<br />
modify :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyLazy :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyField :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
modifyFieldLazy :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
</haskell><br />
<br />
As the names suggest ''StateT'' is strict by default. When setting a new state using <hask>put</hask>, the state is evaluated. If you want to avoid that use <hask>putLazy</hask> instead.<br />
<br />
=== Running ===<br />
<br />
To run a stateful computation you can use the <hask>runStateT</hask> function, which takes a final continuation, an initial state and a stateful computation as arguments. There are two convenience functions <hask>evalStateT</hask><br />
<br />
<haskell><br />
runStateT :: s -> (s -> a -> m r) -> StateT r s m a -> m r<br />
evalStateT :: (Applicative m) => s -> StateT r s m r -> m r<br />
execStateT :: (Applicative m) => s -> StateT s s m a -> m s<br />
</haskell><br />
<br />
In most cases you will just use <hask>evalStateT</hask> or <hask>execStateT</hask>.<br />
<br />
== Exceptions ==<br />
<br />
''Contstuff'' provides an ''EitherT'' monad transformer:<br />
<br />
<haskell><br />
newtype EitherT r e m a<br />
</haskell><br />
<br />
This monad transformer is a generalization of ''ContT'' in that it supports two continuations. The second one can be accessed indirectly by the various exception handling functions.<br />
<br />
=== Raising and catching ===<br />
<br />
There are a number of functions to handle exceptions, which belong to a class <hask>HasExceptions</hask> with an associated type <hask>Exception m</hask>. ''EitherT'' is an instance of this class.<br />
<br />
<haskell><br />
-- Where 'm' is a monad supporting exceptions, 'Exception m' is the<br />
-- type of the exceptions.<br />
raise :: (HasExceptions m) => Exception m -> m a<br />
try :: (HasExceptions m) => m a -> m (Either (Exception m) a)<br />
<br />
-- Convenience functions.<br />
catch :: (HasExceptions m, Monad m) => m a -> (Exception m -> m a) -> m a<br />
handle :: (HasExceptions m, Monad m) => (Exception m -> m a) -> m a -> m a<br />
finally :: (HasExceptions m, Monad m) => m a -> m b -> m a<br />
bracket :: (HasExceptions m, Monad m) =><br />
m res -> (res -> m b) -> (res -> m a) -> m a<br />
bracket_ :: (HasExceptions m, Monad m) => m a -> m b -> m c -> m c<br />
</haskell><br />
<br />
Please note that <hask>bracket</hask> and <hask>bracket_</hask> have slightly different semantics than the corresponding functions from <hask>Control.Exception</hask>. If an exception is raised in both the middle computation and the final computation, then the middle one is significant.<br />
<br />
=== Running ===<br />
<br />
To run an ''EitherT'' computation you can use the <hask>runEitherT</hask> function, which expects the two final continuations and an ''EitherT'' computation. There is also a convenience function <hask>evalEitherT</hask>, which just returns an ''Either'' value:<br />
<br />
<haskell><br />
runEitherT :: (a -> m r) -> (e -> m r) -> EitherT r e m a -> m r<br />
evalEitherT :: (Applicative m) =><br />
EitherT (Either e a) e m a -> m (Either e a)<br />
</haskell><br />
<br />
== Choice/nondeterminism ==<br />
<br />
The ''ChoiceT'' monad transformer is basically a list monad transformer and a proper one at that. It is also very fast, because choice is implemented as a CPS-based left fold function:<br />
<br />
<haskell><br />
newtype ChoiceT r i m a<br />
</haskell><br />
<br />
The parameters <hask>r</hask> and <hask>i</hask> are the types of the final and the intermediate results respectively. In actual computations, unless you use abortion, these can be left polymorphic most of the time. Also practically they are almost always the same. Don't worry about them.<br />
<br />
=== Running ===<br />
<br />
You can run a ''ChoiceT'' computation by using the slightly scary <hask>runChoiceT</hask> function:<br />
<br />
<haskell><br />
runChoiceT ::<br />
(i -> a -> (i -> m r) -> m r) -> i -> (i -> m r)<br />
-> ChoiceT r i m a -> m r<br />
</haskell><br />
<br />
This function takes a folding function, a base element, a final continuation (the folding function uses CPS) and a ''ChoiceT'' computation. Of course in practice you mostly just want a list of results or the first result or something like that. Luckily there are two convenience functions to do just that:<br />
<br />
<haskell><br />
findFirst :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
findAll :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
</haskell><br />
<br />
Even these look scary, but they really aren't. In most cases <hask>f</hask> is just <hask>[]</hask> or <hask>Maybe</hask>. But there are more convenience functions:<br />
<br />
<haskell><br />
maybeChoiceT :: Applicative m =><br />
ChoiceT (Maybe a) (Maybe a) m a -> m (Maybe a)<br />
listChoiceT :: Applicative m => ChoiceT [a] [a] m a -> m [a]<br />
</haskell><br />
<br />
The <hask>maybeChoiceT</hask> function is just a special case of <hask>findFirst</hask>. The <hask>listChoiceT</hask> in contrast does not behave like <hask>findAll</hask>. It returns the results in reversed order and is much faster than <hask>findAll</hask>.<br />
<br />
=== Convenience functions ===<br />
<br />
Often you just want to encode a list of choices. For this you can use the <hask>listA</hask> function discussed earlier:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
There is an alternative function, which works only for ''ChoiceT'', but is much faster than <hask>listA</hask>, called just <hask>choice</hask>:<br />
<br />
<haskell><br />
choice :: [a] -> ChoiceT r i m a<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36896Contstuff2010-09-30T02:00:03Z<p>Ertes: Removed the introduction header</p>
<hr />
<div>The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The ''ContT'' monad transformer is the simplest of all CPS-based monads:<br />
<br />
<haskell><br />
newtype ContT r m a<br />
</haskell><br />
<br />
It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ''ContT'' you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of ''ContT''. If you don't use them, then ''ContT'' behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a ''ContT'' computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of ''ContT''. First of all, ''ContT'' is a monad transformer, so you can for example lift ''IO'' actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the ''IO'' monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to ''ContT''.<br />
<br />
Each ''ContT'' subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m b<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in ''contstuff''. This means you can carry them around. They are only limited in that they can't be carried outside of a ''ContT'' computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: (LiftBase m a) => Base m a -> m a<br />
io :: (Base m a ~ IO a, LiftBase m a) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to ''IO''.<br />
<br />
=== Accumulating results ===<br />
<br />
''ContT'' does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
== State ==<br />
<br />
The ''contstuff'' library also comes with a monad transformer for stateful computations. These computations carry state of a certain type and can access it at any time. It's called ''StateT'', just like in other transformer libraries, but this one has very different semantics and also takes an additional parameter:<br />
<br />
<haskell><br />
newtype StateT r s m a<br />
</haskell><br />
<br />
It is basically a generalization of ''ContT''. In fact you can use all the features of ''ContT'' in a ''StateT'' computation, too, including abortion, labels, accumulation, etc.<br />
<br />
The <hask>r</hask> parameter is the type of the final result. In actual computations this parameter can be left polymorphic most of the time, unless you use abortion.<br />
<br />
=== Accessing the state ===<br />
<br />
There are many functions to access the implicit state. These don't belong to ''StateT'' directly, but instead to a type class called ''Stateful'', of which ''StateT'' is an instance. The associated type <hask>StateOf m</hask> is the type of the state of the monad <hask>m</hask>:<br />
<br />
<haskell><br />
-- Where 'm' is a Stateful monad, 'StateOf m' is the type of its state.<br />
get :: (Stateful m) => m (StateOf m)<br />
put :: (Stateful m) => StateOf m -> m ()<br />
putLazy :: (Stateful m) => StateOf m -> m ()<br />
<br />
-- Convenience functions.<br />
getField :: (Functor m, Stateful m) => (StateOf m -> a) -> m a<br />
modify :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyLazy :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyField :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
modifyFieldLazy :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
</haskell><br />
<br />
As the names suggest ''StateT'' is strict by default. When setting a new state using <hask>put</hask>, the state is evaluated. If you want to avoid that use <hask>putLazy</hask> instead.<br />
<br />
=== Running ===<br />
<br />
To run a stateful computation you can use the <hask>runStateT</hask> function, which takes a final continuation, an initial state and a stateful computation as arguments. There are two convenience functions <hask>evalStateT</hask><br />
<br />
<haskell><br />
runStateT :: s -> (s -> a -> m r) -> StateT r s m a -> m r<br />
evalStateT :: (Applicative m) => s -> StateT r s m r -> m r<br />
execStateT :: (Applicative m) => s -> StateT s s m a -> m s<br />
</haskell><br />
<br />
In most cases you will just use <hask>evalStateT</hask> or <hask>execStateT</hask>.<br />
<br />
== Exceptions ==<br />
<br />
''Contstuff'' provides an ''EitherT'' monad transformer:<br />
<br />
<haskell><br />
newtype EitherT r e m a<br />
</haskell><br />
<br />
This monad transformer is a generalization of ''ContT'' in that it supports two continuations. The second one can be accessed indirectly by the various exception handling functions.<br />
<br />
=== Raising and catching ===<br />
<br />
There are a number of functions to handle exceptions, which belong to a class <hask>HasExceptions</hask> with an associated type <hask>Exception m</hask>. ''EitherT'' is an instance of this class.<br />
<br />
<haskell><br />
-- Where 'm' is a monad supporting exceptions, 'Exception m' is the<br />
-- type of the exceptions.<br />
raise :: (HasExceptions m) => Exception m -> m a<br />
try :: (HasExceptions m) => m a -> m (Either (Exception m) a)<br />
<br />
-- Convenience functions.<br />
catch :: (HasExceptions m, Monad m) => m a -> (Exception m -> m a) -> m a<br />
handle :: (HasExceptions m, Monad m) => (Exception m -> m a) -> m a -> m a<br />
finally :: (HasExceptions m, Monad m) => m a -> m b -> m a<br />
bracket :: (HasExceptions m, Monad m) =><br />
m res -> (res -> m b) -> (res -> m a) -> m a<br />
bracket_ :: (HasExceptions m, Monad m) => m a -> m b -> m c -> m c<br />
</haskell><br />
<br />
Please note that <hask>bracket</hask> and <hask>bracket_</hask> have slightly different semantics than the corresponding functions from <hask>Control.Exception</hask>. If an exception is raised in both the middle computation and the final computation, then the middle one is significant.<br />
<br />
=== Running ===<br />
<br />
To run an ''EitherT'' computation you can use the <hask>runEitherT</hask> function, which expects the two final continuations and an ''EitherT'' computation. There is also a convenience function <hask>evalEitherT</hask>, which just returns an ''Either'' value:<br />
<br />
<haskell><br />
runEitherT :: (a -> m r) -> (e -> m r) -> EitherT r e m a -> m r<br />
evalEitherT :: (Applicative m) =><br />
EitherT (Either e a) e m a -> m (Either e a)<br />
</haskell><br />
<br />
== Choice/nondeterminism ==<br />
<br />
The ''ChoiceT'' monad transformer is basically a list monad transformer and a proper one at that. It is also very fast, because choice is implemented as a CPS-based left fold function:<br />
<br />
<haskell><br />
newtype ChoiceT r i m a<br />
</haskell><br />
<br />
The parameters <hask>r</hask> and <hask>i</hask> are the types of the final and the intermediate results respectively. In actual computations, unless you use abortion, these can be left polymorphic most of the time. Also practically they are almost always the same. Don't worry about them.<br />
<br />
=== Running ===<br />
<br />
You can run a ''ChoiceT'' computation by using the slightly scary <hask>runChoiceT</hask> function:<br />
<br />
<haskell><br />
runChoiceT ::<br />
(i -> a -> (i -> m r) -> m r) -> i -> (i -> m r)<br />
-> ChoiceT r i m a -> m r<br />
</haskell><br />
<br />
This function takes a folding function, a base element, a final continuation (the folding function uses CPS) and a ''ChoiceT'' computation. Of course in practice you mostly just want a list of results or the first result or something like that. Luckily there are two convenience functions to do just that:<br />
<br />
<haskell><br />
findFirst :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
findAll :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
</haskell><br />
<br />
Even these look scary, but they really aren't. In most cases <hask>f</hask> is just <hask>[]</hask> or <hask>Maybe</hask>. But there are more convenience functions:<br />
<br />
<haskell><br />
maybeChoiceT :: Applicative m =><br />
ChoiceT (Maybe a) (Maybe a) m a -> m (Maybe a)<br />
listChoiceT :: Applicative m => ChoiceT [a] [a] m a -> m [a]<br />
</haskell><br />
<br />
The <hask>maybeChoiceT</hask> function is just a special case of <hask>findFirst</hask>. The <hask>listChoiceT</hask> in contrast does not behave like <hask>findAll</hask>. It returns the results in reversed order and is much faster than <hask>findAll</hask>.<br />
<br />
=== Convenience functions ===<br />
<br />
Often you just want to encode a list of choices. For this you can use the <hask>listA</hask> function discussed earlier:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
There is an alternative function, which works only for ''ChoiceT'', but is much faster than <hask>listA</hask>, called just <hask>choice</hask>:<br />
<br />
<haskell><br />
choice :: [a] -> ChoiceT r i m a<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36895Contstuff2010-09-30T01:59:16Z<p>Ertes: Added lots and lots of stuff.</p>
<hr />
<div>== Introduction ==<br />
<br />
The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The ''ContT'' monad transformer is the simplest of all CPS-based monads:<br />
<br />
<haskell><br />
newtype ContT r m a<br />
</haskell><br />
<br />
It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ''ContT'' you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of ''ContT''. If you don't use them, then ''ContT'' behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a ''ContT'' computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of ''ContT''. First of all, ''ContT'' is a monad transformer, so you can for example lift ''IO'' actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the ''IO'' monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to ''ContT''.<br />
<br />
Each ''ContT'' subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m b<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in ''contstuff''. This means you can carry them around. They are only limited in that they can't be carried outside of a ''ContT'' computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: (LiftBase m a) => Base m a -> m a<br />
io :: (Base m a ~ IO a, LiftBase m a) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to ''IO''.<br />
<br />
=== Accumulating results ===<br />
<br />
''ContT'' does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
== State ==<br />
<br />
The ''contstuff'' library also comes with a monad transformer for stateful computations. These computations carry state of a certain type and can access it at any time. It's called ''StateT'', just like in other transformer libraries, but this one has very different semantics and also takes an additional parameter:<br />
<br />
<haskell><br />
newtype StateT r s m a<br />
</haskell><br />
<br />
It is basically a generalization of ''ContT''. In fact you can use all the features of ''ContT'' in a ''StateT'' computation, too, including abortion, labels, accumulation, etc.<br />
<br />
The <hask>r</hask> parameter is the type of the final result. In actual computations this parameter can be left polymorphic most of the time, unless you use abortion.<br />
<br />
=== Accessing the state ===<br />
<br />
There are many functions to access the implicit state. These don't belong to ''StateT'' directly, but instead to a type class called ''Stateful'', of which ''StateT'' is an instance. The associated type <hask>StateOf m</hask> is the type of the state of the monad <hask>m</hask>:<br />
<br />
<haskell><br />
-- Where 'm' is a Stateful monad, 'StateOf m' is the type of its state.<br />
get :: (Stateful m) => m (StateOf m)<br />
put :: (Stateful m) => StateOf m -> m ()<br />
putLazy :: (Stateful m) => StateOf m -> m ()<br />
<br />
-- Convenience functions.<br />
getField :: (Functor m, Stateful m) => (StateOf m -> a) -> m a<br />
modify :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyLazy :: (Monad m, Stateful m) => (StateOf m -> StateOf m) -> m ()<br />
modifyField :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
modifyFieldLazy :: (Monad m, Stateful m) =><br />
(StateOf m -> a) -> (a -> StateOf m) -> m ()<br />
</haskell><br />
<br />
As the names suggest ''StateT'' is strict by default. When setting a new state using <hask>put</hask>, the state is evaluated. If you want to avoid that use <hask>putLazy</hask> instead.<br />
<br />
=== Running ===<br />
<br />
To run a stateful computation you can use the <hask>runStateT</hask> function, which takes a final continuation, an initial state and a stateful computation as arguments. There are two convenience functions <hask>evalStateT</hask><br />
<br />
<haskell><br />
runStateT :: s -> (s -> a -> m r) -> StateT r s m a -> m r<br />
evalStateT :: (Applicative m) => s -> StateT r s m r -> m r<br />
execStateT :: (Applicative m) => s -> StateT s s m a -> m s<br />
</haskell><br />
<br />
In most cases you will just use <hask>evalStateT</hask> or <hask>execStateT</hask>.<br />
<br />
== Exceptions ==<br />
<br />
''Contstuff'' provides an ''EitherT'' monad transformer:<br />
<br />
<haskell><br />
newtype EitherT r e m a<br />
</haskell><br />
<br />
This monad transformer is a generalization of ''ContT'' in that it supports two continuations. The second one can be accessed indirectly by the various exception handling functions.<br />
<br />
=== Raising and catching ===<br />
<br />
There are a number of functions to handle exceptions, which belong to a class <hask>HasExceptions</hask> with an associated type <hask>Exception m</hask>. ''EitherT'' is an instance of this class.<br />
<br />
<haskell><br />
-- Where 'm' is a monad supporting exceptions, 'Exception m' is the<br />
-- type of the exceptions.<br />
raise :: (HasExceptions m) => Exception m -> m a<br />
try :: (HasExceptions m) => m a -> m (Either (Exception m) a)<br />
<br />
-- Convenience functions.<br />
catch :: (HasExceptions m, Monad m) => m a -> (Exception m -> m a) -> m a<br />
handle :: (HasExceptions m, Monad m) => (Exception m -> m a) -> m a -> m a<br />
finally :: (HasExceptions m, Monad m) => m a -> m b -> m a<br />
bracket :: (HasExceptions m, Monad m) =><br />
m res -> (res -> m b) -> (res -> m a) -> m a<br />
bracket_ :: (HasExceptions m, Monad m) => m a -> m b -> m c -> m c<br />
</haskell><br />
<br />
Please note that <hask>bracket</hask> and <hask>bracket_</hask> have slightly different semantics than the corresponding functions from <hask>Control.Exception</hask>. If an exception is raised in both the middle computation and the final computation, then the middle one is significant.<br />
<br />
=== Running ===<br />
<br />
To run an ''EitherT'' computation you can use the <hask>runEitherT</hask> function, which expects the two final continuations and an ''EitherT'' computation. There is also a convenience function <hask>evalEitherT</hask>, which just returns an ''Either'' value:<br />
<br />
<haskell><br />
runEitherT :: (a -> m r) -> (e -> m r) -> EitherT r e m a -> m r<br />
evalEitherT :: (Applicative m) =><br />
EitherT (Either e a) e m a -> m (Either e a)<br />
</haskell><br />
<br />
== Choice/nondeterminism ==<br />
<br />
The ''ChoiceT'' monad transformer is basically a list monad transformer and a proper one at that. It is also very fast, because choice is implemented as a CPS-based left fold function:<br />
<br />
<haskell><br />
newtype ChoiceT r i m a<br />
</haskell><br />
<br />
The parameters <hask>r</hask> and <hask>i</hask> are the types of the final and the intermediate results respectively. In actual computations, unless you use abortion, these can be left polymorphic most of the time. Also practically they are almost always the same. Don't worry about them.<br />
<br />
=== Running ===<br />
<br />
You can run a ''ChoiceT'' computation by using the slightly scary <hask>runChoiceT</hask> function:<br />
<br />
<haskell><br />
runChoiceT ::<br />
(i -> a -> (i -> m r) -> m r) -> i -> (i -> m r)<br />
-> ChoiceT r i m a -> m r<br />
</haskell><br />
<br />
This function takes a folding function, a base element, a final continuation (the folding function uses CPS) and a ''ChoiceT'' computation. Of course in practice you mostly just want a list of results or the first result or something like that. Luckily there are two convenience functions to do just that:<br />
<br />
<haskell><br />
findFirst :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
findAll :: (Alternative f, Applicative m) =><br />
ChoiceT (f a) (f a) m a -> m (f a)<br />
</haskell><br />
<br />
Even these look scary, but they really aren't. In most cases <hask>f</hask> is just <hask>[]</hask> or <hask>Maybe</hask>. But there are more convenience functions:<br />
<br />
<haskell><br />
maybeChoiceT :: Applicative m =><br />
ChoiceT (Maybe a) (Maybe a) m a -> m (Maybe a)<br />
listChoiceT :: Applicative m => ChoiceT [a] [a] m a -> m [a]<br />
</haskell><br />
<br />
The <hask>maybeChoiceT</hask> function is just a special case of <hask>findFirst</hask>. The <hask>listChoiceT</hask> in contrast does not behave like <hask>findAll</hask>. It returns the results in reversed order and is much faster than <hask>findAll</hask>.<br />
<br />
=== Convenience functions ===<br />
<br />
Often you just want to encode a list of choices. For this you can use the <hask>listA</hask> function discussed earlier:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
There is an alternative function, which works only for ''ChoiceT'', but is much faster than <hask>listA</hask>, called just <hask>choice</hask>:<br />
<br />
<haskell><br />
choice :: [a] -> ChoiceT r i m a<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36894Contstuff2010-09-30T00:50:28Z<p>Ertes: Changed formatting</p>
<hr />
<div>== Introduction ==<br />
<br />
The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The ''ContT'' monad transformer is the simplest of all CPS-based monads. It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ''ContT'' you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of ''ContT''. If you don't use them, then ''ContT'' behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a ''ContT'' computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of ''ContT''. First of all, ''ContT'' is a monad transformer, so you can for example lift ''IO'' actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the ''IO'' monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to ''ContT''.<br />
<br />
Each ''ContT'' subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m b<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in ''contstuff''. This means you can carry them around. They are only limited in that they can't be carried outside of a ''ContT'' computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: (LiftBase m a) => Base m a -> m a<br />
io :: (Base m a ~ IO a, LiftBase m a) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to ''IO''.<br />
<br />
=== Accumulating results ===<br />
<br />
''ContT'' does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell></div>Erteshttps://wiki.haskell.org/index.php?title=Contstuff&diff=36808Contstuff2010-09-20T23:49:07Z<p>Ertes: Added a lot of stuff.</p>
<hr />
<div>== Introduction ==<br />
<br />
The [http://hackage.haskell.org/package/contstuff contstuff library] implements a number of monad transformers and monads, which make heavy use of [[continuation passing style]] (CPS). This makes them both fast and flexible. Please note that this is neither a CPS tutorial nor a monad transformer tutorial. You should understand these concepts, before attempting to use ''contstuff''.<br />
<br />
== Basics ==<br />
=== ContT ===<br />
<br />
The <hask>ContT</hask> monad transformer is the simplest of all CPS-based monads. It essentially gives you access to the current continuation, which means that it lets you label certain points of execution and reuse these points later in interesting ways. With ContT you get an elegant encoding of computations, which support:<br />
<br />
* abortion (premature termination),<br />
* resumption (start a computation at a certain spot),<br />
* branches (aka ''goto''),<br />
* result accumulation,<br />
* etc.<br />
<br />
All these features are effects of <hask>ContT</hask>. If you don't use them, then <hask>ContT</hask> behaves like the identity monad. A computation of type <hask>ContT r m a</hask> is a CPS computation with an intermediate result of type <hask>a</hask> and a final result of type <hask>r</hask>. The <hask>r</hask> type can be polymorphic most of the time. You only need to specify it, if you use some of the CPS effects like <hask>abort</hask>.<br />
<br />
To run a <hask>ContT</hask> computation you can use <hask>runContT</hask> or the convenience function <hask>evalContT</hask>:<br />
<br />
<haskell><br />
runContT :: (a -> m r) -> ContT r m a -> m r<br />
evalContT :: Applicative m => ContT r m r -> m r<br />
</haskell><br />
<br />
The <hask>runContT</hask> function takes a final continuation transforming the last intermediate result into a final result. The <hask>evalContT</hask> function simply passes <hask>pure</hask> as the final continuation.<br />
<br />
=== Abortion ===<br />
<br />
Let's have a look at a small example:<br />
<br />
<haskell><br />
testComp1 :: ContT () IO ()<br />
testComp1 =<br />
forever $ do<br />
txt <- io getLine<br />
case txt of<br />
"info" -> io $ putStrLn "This is a test computation."<br />
"quit" -> abort ()<br />
_ -> return ()<br />
</haskell><br />
<br />
This example demonstrates the most basic feature of <hask>ContT</hask>. First of all, <hask>ContT</hask> is a monad transformer, so you can for example lift IO actions to a CPS computation. The <hask>io</hask> function is a handy tool, which corresponds to <hask>liftIO</hask> from other transformer libraries and to <hask>inBase</hask> from [[monadLib]], but is restricted to the <hask>IO</hask> monad. You can also use the more generic <hask>base</hask> function, which promotes a base monad computation to <hask>ContT</hask>.<br />
<br />
Each <hask>ContT</hask> subcomputation receives a continuation, which is a function, to which the subcomputation is supposed to pass the result. However, the subcomputation may choose not to call the continuation at all, in which case the entire computation finishes with a final result. The <hask>abort</hask> function does that.<br />
<br />
=== Resumption and branches ===<br />
<br />
You can capture the current continuation using the common <hask>callCC</hask> function. If you just need branches, there are two handy functions for this:<br />
<br />
<haskell><br />
labelCC :: a -> ContT r m (a, Label (ContT r m) a)<br />
goto :: Label (ContT r m) a -> a -> ContT r m b<br />
</haskell><br />
<br />
These slightly complicated looking functions are actually very simple to use:<br />
<br />
<haskell><br />
testComp2 :: ContT r IO ()<br />
testComp2 = do<br />
(i, again) <- labelCC 0<br />
io (print i)<br />
when (i < 10) $ goto again (i+1)<br />
io (putStrLn $ "Final result: " ++ show i)<br />
</haskell><br />
<br />
The <hask>labelCC</hask> function establishes a label to jump to by capturing its own continuation. It returns both its argument and a label. The <hask>goto</hask> function takes a label and a new argument. The effect is jumping to the corresponding label, but returning the new argument. So when <hask>labelCC</hask> is reached the <hask>i</hask> variable becomes 0. Later <hask>goto</hask> jumps back to the same point, but gives <hask>i</hask> a new value 1, as if <hask>labelCC</hask> were originally called with 1 as the argument.<br />
<br />
Labels are first class values in contstuff. This means you can carry them around. They are only limited in that they can't be carried outside of a <hask>ContT</hask> computation.<br />
<br />
=== Lifting ===<br />
<br />
As noted earlier there are three lifting functions, which you can use to access monads in lower layers of the transformer stack:<br />
<br />
<haskell><br />
lift :: (Transformer t, Monad m) => m a -> t m a<br />
base :: (LiftBase m a) => Base m a -> m a<br />
io :: (Base m a ~ IO a, LiftBase m a) => Base m a -> m a<br />
</haskell><br />
<br />
The <hask>lift</hask> function promotes a computation of the underlying monad. The <hask>base</hask> function promotes a computation of the base monad. It is a generalization of <hask>liftIO</hask> from other monad transformer libraries. Finally there is <hask>io</hask>, which is simply an alias for <hask>base</hask>, but restricted to <hask>IO</hask>.<br />
<br />
=== Accumulating results ===<br />
<br />
<hask>ContT</hask> does not require the underlying functor to be a monad. Whenever the underlying functor is an <hask>Alternative</hask> functor, there is support for accumulating results using the <hask>(<|>)</hask> combinator. In other words, if <hask>m</hask> is an <hask>Alternative</hask>, then <hask>ContT r m</hask> is, too. Here is an example:<br />
<br />
<haskell><br />
testComp3 :: Num a => ContT r [] (a, a)<br />
testComp3 = do<br />
x <- pure 10 <|> pure 20<br />
y <- pure (x+1) <|> pure (x-1)<br />
return (x, y)<br />
</haskell><br />
<br />
The ''contstuff'' library implements a convenience function <hask>listA</hask>, which turns a list into an <hask>Alternative</hask> computation:<br />
<br />
<haskell><br />
listA :: (Alternative f) => [a] -> f a<br />
</haskell><br />
<br />
Using this you can simplify <hask>testComp3</hask> to:<br />
<br />
<haskell><br />
testComp3' :: Num a => ContT r [] (a, a)<br />
testComp3' = do<br />
x <- listA [10, 20]<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell><br />
<br />
You can collapse branches using <hask>abort</hask>:<br />
<br />
<haskell><br />
testComp4 :: Num a => ContT (a, a) [] (a, a)<br />
testComp4 = do<br />
x <- listA [10, 20]<br />
when (x == 10) (abort (10, 10))<br />
y <- listA [x+1, x-1]<br />
return (x, y)<br />
</haskell></div>Ertes