<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Conal Elliott &#187; segment</title>
	<atom:link href="http://conal.net/blog/tag/segment/feed" rel="self" type="application/rss+xml" />
	<link>http://conal.net/blog</link>
	<description>Inspirations &#38; experiments, mainly about denotative/functional programming in Haskell</description>
	<lastBuildDate>Thu, 25 Jul 2019 18:15:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.17</generator>
	<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2F&amp;language=en_US&amp;category=text&amp;title=Conal+Elliott&amp;description=Inspirations+%26amp%3B+experiments%2C+mainly+about+denotative%2Ffunctional+programming+in+Haskell&amp;tags=blog" type="text/html" />
	<item>
		<title>Sequences, segments, and signals</title>
		<link>http://conal.net/blog/posts/sequences-segments-and-signals</link>
		<comments>http://conal.net/blog/posts/sequences-segments-and-signals#comments</comments>
		<pubDate>Fri, 05 Dec 2008 08:14:33 +0000</pubDate>
		<dc:creator><![CDATA[Conal]]></dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[applicative functor]]></category>
		<category><![CDATA[comonad]]></category>
		<category><![CDATA[FRP]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[functional reactive programming]]></category>
		<category><![CDATA[functor]]></category>
		<category><![CDATA[monoid]]></category>
		<category><![CDATA[segment]]></category>
		<category><![CDATA[sequence]]></category>
		<category><![CDATA[type class morphism]]></category>
		<category><![CDATA[zipper]]></category>

		<guid isPermaLink="false">http://conal.net/blog/?p=67</guid>
		<description><![CDATA[The post Sequences, streams, and segments offered an answer to the the question of what&#8217;s missing in the following box: infinitefinite discreteStream Sequence continuousFunction ??? I presented a simple type of function segments, whose representation contains a length (duration) and a function. This type implements most of the usual classes: Monoid, Functor, Zip, and Applicative, [&#8230;]]]></description>
				<content:encoded><![CDATA[<!-- 

Title: Sequences, segments, and signals

Tags: function, sequence, monoid, functor, applicative functor, comonad, FRP, functional reactive programming, segment, type class morphism, zipper

URL: http://conal.net/blog/posts/sequences-segments-and-signals/

-->

<!-- references -->

<!-- teaser -->

<p>The post <em><a href="http://conal.net/blog/posts/sequences-streams-and-segments/" title="blog post">Sequences, streams, and segments</a></em> offered an answer to the the question of what&#8217;s missing in the following box:</p>

<div align=center style="margin-bottom:10px">
  <table border="2">
    <tr><td></td><td style="text-align:center;padding:5px"><strong>infinite</strong><td style="text-align:center;padding:5px"><strong>finite</strong></third></tr>
    <tr><td style="text-align:center;padding:5px"><strong>discrete</strong><td style="text-align:center;padding:7px">Stream</td> <td style="text-align:center;padding:7px">Sequence</td></tr>
    <tr><td style="text-align:center;padding:5px"><strong>continuous</strong><td style="text-align:center;padding:7px">Function</td> <td style="text-align:center;padding:7px"><em>???</em></td></tr>
  </table>
</div>

<p>I presented a simple type of <em>function segments</em>, whose representation contains a length (duration) and a function.
This type implements most of the usual classes: <code>Monoid</code>, <code>Functor</code>, <code>Zip</code>, and <code>Applicative</code>, as well <code>Comonad</code>, but not <code>Monad</code>.
It also implements a new type class, <code>Segment</code>, which generalizes the list functions <code>length</code>, <code>take</code>, and <code>drop</code>.</p>

<p>The function type is simple and useful in itself.
I believe it can also serve as a semantic foundation for functional reactive programming (FRP), as I&#8217;ll explain in another post.
However, the type has a serious performance problem that makes it impractical for some purposes, including as implementation of FRP.</p>

<p>Fortunately, we can solve the performance problem by adding a simple layer on top of function segments, to get what I&#8217;ll call &#8220;signals&#8221;.
With this new layer, we have an efficient replacement for function segments that implements exactly the same interface with exactly the same semantics.
Pleasantly, the class instances are defined fairly simply in terms of the corresponding instances on function segments.</p>

<p>You can download the <a href="http://conal.net/blog/code/Signal.hs">code for this post</a>.</p>

<p><strong>Edits</strong>:</p>

<ul>
<li>2008-12-06: <code>dup [] = []</code> near the end (was <code>[mempty]</code>).</li>
<li>2008-12-09: Fixed <code>take</code> and <code>drop</code> default definitions (thanks to sclv) and added point-free variant.</li>
<li>2008-12-18: Fixed <code>appl</code>, thanks to sclv.</li>
<li>2011-08-18: Eliminated accidental emoticon in the definition of <code>dup</code>, thanks to anonymous.</li>
</ul>

<!-- without a comment or something here, the last item above becomes a paragraph -->

<p><span id="more-67"></span></p>

<h3>The problem with function segments</h3>

<p>The type of function segments is defined as follows:</p>

<pre><code>data t :-&gt;# a = FS t (t -&gt; a)
</code></pre>

<p>The domain of the function segment is from zero up to but not including the given length.</p>

<p>An efficiency problem becomes apparent when we look at the <code>Monoid</code> instance:</p>

<pre><code>instance (Ord t, Num t) =&gt; Monoid (t :-&gt;# a) where
    mempty = FS 0 (error "sampling empty 't :-&gt;# a'")
    FS c f `mappend` FS d g =
      FS (c + d) ( t -&gt; if t &lt;= c then f t else g (t - c))
</code></pre>

<p>Concatenation (<code>mappend</code>) creates a new segment that chooses, for every domain value <code>t</code>, whether to use one function or another.
If the second, then <code>t</code> must be shifted backward, since the function is being shifted forward.</p>

<p>This implementation would be fine if we use <code>mappend</code> just on simple segments.
Once we get started, however, we&#8217;ll want to concatenate lots &amp; lots of segments.
In FRP, time-varying values go through many phases (segments) as time progresses.
Each quantity is described by a single &#8220;behavior&#8221; (sometimes called a &#8220;signal&#8221;) with many, and often infinitely many, phases.
Imagine an infinite tree of concatenations, which is typical for FRP behaviors.
At every moment, one phase is active.
Every sampling must recursively discover the active phase and the accumulated domain translation (from successive subtractions) to apply when sampling that phase.
Quite commonly, concatenation trees get progressively deeper on the right (larger <code>t</code> values).
In that case, sampling will get slower and slower with time.</p>

<p>I like to refer to these progressive slow-downs as &#8220;time leaks&#8221;.
There is also a serious space leak, since all of the durations and functions that go into a composed segment will be retained.</p>

<h3>Sequences of segments</h3>

<p>The problem above can be solved with a simple representation change.
Instead of combining functions into functions, just keep a list of simple function segments.</p>

<pre><code>-- | Signal indexed by t with values of type a.
newtype t :-&gt; a = S { unS :: [t :-&gt;# a] }
</code></pre>

<p>I&#8217;ll restrict in function segments to be <em>non-empty</em>, to keep the rest of the implementation simple and efficient.</p>

<p>This new representation allows for efficient <em>monotonic</em> sampling of signals.
As old segments are passed up, they can be dropped.</p>

<h4>What does it mean?</h4>

<p>There&#8217;s one central question for me in defining any data type: <em>What does it mean?</em></p>

<p>The meaning I&#8217;ll take for signals is function segments.
This interpretation is made precise in a function that maps from the type to the model (meaning).
In this case, simply concatenate all of the function segments:</p>

<pre><code>meaning :: (Ord t, Num t) =&gt; (t :-&gt; a) -&gt; (t :-&gt;# a)
meaning = mconcat . unS
</code></pre>

<p>Specifying the meaning of a type gives users a working model, and it defines correctness of implementation.
It also tells me what class instances to implement and tells users what instances to expect.
If a type&#8217;s meaning implements a class then I want the type to as well.
Moreover, the type&#8217;s intances have to agree with the model&#8217;s instances.
I&#8217;ve described this latter principle in <em><a href="http://conal.net/blog/posts/simplifying-semantics-with-type-class-morphisms" title="blog post">Simplifying semantics with type class morphisms</a></em> and <a href="http://conal.net/blog/tag/type-class-morphism/" title="Posts on type class morphisms">some other posts</a>.</p>

<h4>Higher-order wrappers</h4>

<p>To keep the code below short and clear, I&#8217;ll use some functions for adding and removing the newtype wrappers.
These higher-order function apply functions inside of <code>(:-&gt;)</code> representations:</p>

<pre><code>inS  :: ([s :-&gt;# a] -&gt; [t :-&gt;# b])
     -&gt; ((s :-&gt;  a) -&gt; (t :-&gt;  b))

inS2 :: ([s :-&gt;# a] -&gt; [t :-&gt;# b] -&gt; [u :-&gt;# c])
     -&gt; ((s :-&gt;  a) -&gt; (t :-&gt;  b) -&gt; (u :-&gt;  c))
</code></pre>

<p>Using the trick described in <em><a href="http://conal.net/blog/posts/prettier-functions-for-wrapping-and-wrapping/" title="blog post">Prettier functions for wrapping and wrapping</a></em>, the definitions are simpler than the types:</p>

<pre><code>inS  = result   S . argument unS
inS2 = result inS . argument unS
</code></pre>

<h4><code>Functor</code></h4>

<p>The <code>Functor</code> instance applies a given function inside the function segments inside the lists:</p>

<pre><code>instance Functor ((:-&gt;) t) where
    fmap h (S ss) = S (fmap (fmap h) ss)
</code></pre>

<p>Or, in the style of <em><a href="http://conal.net/blog/posts/semantic-editor-combinators/" title="blog post">Semantic editor combinators</a></em>,</p>

<pre><code>instance Functor ((:-&gt;) t) where
    fmap = inS . fmap . fmap
</code></pre>

<p>Why this definition?
Because it is correct with respect to the semantic model, i.e., the meaning of <code>fmap</code> is <code>fmap</code> of the meaning, i.e.,</p>

<pre><code> meaning . fmap h == fmap h . meaning
</code></pre>

<p>which is to say that the following diagram commutes:</p>

<div align=center><img src="http://conal.net/blog/pictures/signal-meaning-fmap-morphism.png"/></div>

<p>Proof:</p>

<pre><code>meaning . fmap h 

  == {- fmap definition -}

meaning . S . fmap (fmap h) . unS

  == {- meaning definition -}

mconcat . unS . S . fmap (fmap h) . unS

  == {- unS and S are inverses  -}

mconcat . fmap (fmap h) . unS

  == {- fmap h distributes over mappend -}

fmap h . mconcat . unS

  == {- meaning definition -}

fmap . meaning
</code></pre>

<h4><code>Applicative</code> and <code>Zip</code></h4>

<p>Again, the <code>meaning</code> functions tells us what the <code>Applicative</code> instance has to mean.
We only get to choose how to implement that meaning correctly.
The <code>Applicative</code> <a href="http://conal.net/blog/tag/type-class-morphism/" title="Posts on type class morphisms">morphism properties</a>:</p>

<pre><code>meaning (pure a)    == pure a
meaning (bf &lt;*&gt; bx) == meaning bf &lt;*&gt; meaning bx
</code></pre>

<p>Our <code>Applicative</code> instance has a definition similar in simplicity and style to the <code>Functor</code> instance, assuming a worker function <code>appl</code> for <code>(&lt;*&gt;)</code>:</p>

<pre><code>instance (Ord t, Num t, Bounded t) =&gt; Applicative ((:-&gt;) t) where
    pure  = S . pure . pure
    (&lt;*&gt;) = inS2 appl

appl :: (Ord t, Num t, Bounded t) =&gt;
        [t :-&gt;# (a -&gt; b)] -&gt; [t :-&gt;# a] -&gt; [t :-&gt;# b]
</code></pre>

<p>This worker function is somewhat intricate.
At least my implementation of it is, and perhaps there&#8217;s a simpler one.</p>

<p>Again, the <code>meaning</code> functions tells us what the <code>Applicative</code> instance has to mean.
We only get to choose how to implement that meaning correctly.</p>

<p>First, if either segment list runs out, the combination runs out (because the same is true for the <em>meaning</em> of signals).</p>

<pre><code>[] `appl` _  = []

_  `appl` [] = []
</code></pre>

<p>If neither segment list is empty, open up the first segment.
Split the longer segment into a prefix that matches the shorter segment, and combine the two segments with <code>(&lt;*&gt;)</code> (on function segments).
Toss the left-over piece back in its list, and continue.</p>

<pre><code>(fs:fss') `appl` (xs:xss')
   | fd == xd  = (fs  &lt;*&gt; xs ) : (fss' `appl`       xss' )
   | fd &lt;  xd  = (fs  &lt;*&gt; xs') : (fss' `appl` (xs'':xss'))
   | otherwise = (fs' &lt;*&gt; xs ) : ((fs'':fss') `appl` xss')
 where
   fd         = length fs
   xd         = length xs
   (fs',fs'') = splitAt xd fs
   (xs',xs'') = splitAt fd xs
</code></pre>

<p>A <code>Zip</code> instance is easy as always with applicative functors:</p>

<pre><code>instance (Ord t, Num t, Bounded t) =&gt; Zip ((:-&gt;) t) where zip = liftA2 (,)
</code></pre>

<h4><code>Monoid</code></h4>

<p>The <code>Monoid</code> instance:</p>

<pre><code>instance Monoid (t :-&gt; a) where
  mempty = S []
  S xss `mappend` S yss = S (xss ++ yss)
</code></pre>

<p>Correctness follows from properties of <code>mconcat</code> (as used in the <code>meaning</code> function).</p>

<p>We&#8217;re really just using the <code>Monoid</code> instance for the underlying representation, i.e.,</p>

<pre><code>instance Monoid (t :-&gt; a) where
    mempty  = S mempty
    mappend = inS2 mappend
</code></pre>

<h4><code>Segment</code></h4>

<p>The <code>Segment</code> class has <code>length</code>, <code>take</code> and <code>drop</code>.
It&#8217;s handy to include also <code>null</code> and <code>splitAt</code>, both modeled after their counterparts on lists.</p>

<p>The new &amp; improved <code>Segment</code> class:</p>

<pre><code>class Segment seg dur | seg -&gt; dur where
    null    :: seg -&gt; Bool
    length  :: seg -&gt; dur
    take    :: dur -&gt; seg -&gt; seg
    drop    :: dur -&gt; seg -&gt; seg
    splitAt :: dur -&gt; seg -&gt; (seg,seg)
    -- Defaults:
    splitAt d s = (take d s, drop d s)
    take    d s = fst (splitAt d s)
    drop    d s = snd (splitAt d s)
</code></pre>

<p>If we wanted to require <code>dur</code> to be numeric, we could add a default for <code>null</code> as well.
This default could be quite expensive in some cases.
(In the style of <em><a href="http://conal.net/blog/posts/semantic-editor-combinators/" title="blog post">Semantic editor combinators</a></em>, <code>take = (result.result) fst splitAt</code>, and similarly for <code>drop</code>.)</p>

<p>The <code>null</code> and <code>length</code> definitions are simple, following from to properties of <code>mconcat</code>.</p>

<pre><code>instance (Ord t, Num t) =&gt; Segment (t :-&gt; a) t where
  null   (S xss) = null xss
  length (S xss) = sum (length &lt;$&gt; xss)
  ...
</code></pre>

<p>The null case says that the signal is empty exactly when there are no function segments.
This simple definition relies on our restriction to non-empty function segments.
If we drop that restriction, we&#8217;d have to check that every segment is empty:</p>

<pre><code>  -- Alternative definition
  null (S xss) = all null xss
</code></pre>

<p>The <code>length</code> is just the sum of the lengths.</p>

<p>The tricky piece is <code>splitAt</code> (used to define both <code>take</code> and drop), which must assemble segments to satisfy the requested prefix length.
The last segment used might have to get split into two, with one part going into the prefix and one to the suffix.</p>

<pre><code>  splitAt _ (S [])  = (mempty,mempty)
  splitAt d b | d &lt;= 0 = (mempty, b)
  splitAt d (S (xs:xss')) =
    case (d `compare` xd) of
      EQ -&gt; (S [xs], S xss')
      LT -&gt; let (xs',xs'') = splitAt d xs in
              (S [xs'], S (xs'':xss'))
      GT -&gt; let (S uss, suffix) = splitAt (d-xd) (S xss') in
              (S (xs:uss), suffix)
   where
     xd = length xs
</code></pre>

<h4><code>Copointed</code> and <code>Comonad</code></h4>

<p>To extract an element from a signal, extract an element from its first function segment.
Awkwardly, extraction will fail (produce &perp;/error) when the signal is empty.</p>

<pre><code>instance Num t =&gt; Copointed ((:-&gt;) t) where
    extract (S [])     = error "extract: empty S"
    extract (S (xs:_)) = extract xs
</code></pre>

<p>I&#8217;ve exploited our restriction to non-empty function segments.
Otherwise, <code>extract</code> would have to skip past the empty ones:</p>

<pre><code>-- Alternative definition
instance Num t =&gt; Copointed ((:-&gt;) t) where
    extract (S []) = error "extract: empty S"
    extract (S (xs:xss'))
      | null xs     = extract (S xss')
      | otherwise   = extract xs
</code></pre>

<p>The error/&perp; in this definition is dicey, as is the one for function segments.
If we allow the same abuse in order to define a list <code>Copointed</code>, we can get an alternative to the first definition that is prettier but gives a less helpful error message:</p>

<pre><code>instance Num t =&gt; Copointed ((:-&gt;) t) where
    extract = extract . extract . unS
</code></pre>

<p>See the closing remarks for more about this diciness.</p>

<p>Finally, we have <code>Comonad</code>, with its <code>duplicate</code> method.</p>

<pre><code>duplicate :: (t :-&gt; a) -&gt; (t :-&gt; (t :-&gt; a))
</code></pre>

<p>I get confused with wrapping and unwrapping, so let&#8217;s separate the definition into a packaging part and a content part.</p>

<pre><code>instance (Ord t, Num t) =&gt; Comonad ((:-&gt;) t) where
    duplicate = fmap S . inS dup
</code></pre>

<p>with content part:</p>

<pre><code>dup :: (Ord t, Num t) =&gt; [t :-&gt;# a] -&gt; [t :-&gt;# [t :-&gt;# a]]
</code></pre>

<p><!-- 
I think of `duplicate` as forming all of the *tails* of a segment (as it does with lists via the standard `tails` function). 
-->
The helper function, <code>dup</code>, takes each function segment and prepends each of its tails onto the remaining list of segments.</p>

<p>If the segment list is empty, then it has only one tail, also empty.</p>

<pre><code>dup []        = []

dup (xs:xss') = ((: xss') &lt;$&gt; duplicate xs) : dup xss'
</code></pre>

<h3>Closing remarks</h3>

<ul>
<li><p>The definitions above use the function segment type only through its type class interfaces, and so can all of them can be generalized.
Several definitions rely on the <code>Segment</code> instance, but otherwise, each method for the composite type relies on the corresponding method for the underlying segment type.
(For instance, <code>fmap</code> uses <code>fmap</code>, <code>(&lt;*&gt;)</code> uses <code>(&lt;*&gt;)</code>, <code>Segment</code> uses <code>Segment</code>, etc.)
This generality lets us replace function segments with more efficient representations, e.g., doing constant propagation, as in <a href="http://haskell.org/haskellwiki/Reactive" title="Wiki page for the Reactive library">Reactive</a>.
We can also generalize from lists in the definitions above.</p></li>
<li><p>Even without concatenation, function segments can become expensive when <code>drop</code> is repeatedly applied, because function shifts accumulate (e.g., <code>f . (+ 0.01) . (+ 0.01) ....</code>).
A more <code>drop</code>-friendly representation for function segments would be a function and an offset.
Successive drops would add offsets, and <code>extract</code> would always apply the function to its offset.
This representation is similar to the <code>FunArg</code> comonad, mentioned in <a href="http://cs.ioc.ee/~tarmo/papers/essence.pdf" title="Paper by Tarmo Uustalu and Varmo Vene">The Essence of Dataflow Programming</a> (Section 5.2).</p></li>
<li><p>The list-of-segments representation enables efficient monotonic sampling, simply by dropping after each sample.
A variation is to use a list zipper instead of a list.
Then non-monotonic sampling will be efficient as long as successive samplings are for nearby domain values.
Switching to multi-directional representation would lose the space efficiency of unidirectional representations.
The latter work well with lazy evaluation, often running in constant space, because old values are recycled while new values are getting evaluated.</p></li>
<li><p>Still another variation is to use a binary tree instead of a list, to avoid the list append in the <code>Monoid</code> instance for <code>(t :-&gt; a)</code>.
A tree zipper would allow non-monotonic sampling.
Sufficient care in data structure design could perhaps yield efficient random access.</p></li>
<li><p>There&#8217;s a tension between the <code>Copointed</code> and <code>Monoid</code> interfaces.
<code>Copointed</code> has <code>extract</code>, and <code>Monoid</code> has <code>mempty</code>, so what is the value of <code>extract mempty</code>?
Given that <code>Copointed</code> is parameterized over <em>arbitrary</em> types, the only possible answer seems to be &perp; (as in the use of <code>error</code> above).
I don&#8217;t know if the comonad laws can all hold for possibly-empty function segments or for possibly-empty signals.
I&#8217;m grateful to <a href="http://comonad.com/reader/">Edward Kmett</a> for helping me understand this conflict.
He suggested using two coordinated types, one possibly-empty (a monoid) and the other non-empty (a comonad).
I&#8217;m curious to see whether that idea works out.</p></li>
</ul>
<p><a href="http://conal.net/blog/?flattrss_redirect&amp;id=67&amp;md5=e15e8c9dfd9e8f9c0aadd8dc805515dc"><img src="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png" srcset="http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@2x.png 2xhttp://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white.png, http://conal.net/blog/wp-content/plugins/flattr/img/flattr-badge-white@3x.png 3x" alt="Flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://conal.net/blog/posts/sequences-segments-and-signals/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=conal&amp;popout=1&amp;url=http%3A%2F%2Fconal.net%2Fblog%2Fposts%2Fsequences-segments-and-signals&amp;language=en_GB&amp;category=text&amp;title=Sequences%2C+segments%2C+and+signals&amp;description=The+post+Sequences%2C+streams%2C+and+segments+offered+an+answer+to+the+the+question+of+what%26%238217%3Bs+missing+in+the+following+box%3A+infinitefinite+discreteStream+Sequence+continuousFunction+%3F%3F%3F+I+presented+a+simple+type...&amp;tags=applicative+functor%2Ccomonad%2CFRP%2Cfunction%2Cfunctional+reactive+programming%2Cfunctor%2Cmonoid%2Csegment%2Csequence%2Ctype+class+morphism%2Czipper%2Cblog" type="text/html" />
	</item>
	</channel>
</rss>
