PLFA agda exercises
---
title     : "Streams: Streams and coinduction"
permalink : /Streams
---

This chapter introduces streams and coinduction.

## Imports

\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; sym; trans; cong)
open Eq.≡-Reasoning
open import Coinduction using (∞; ♯_; ♭)
open import Data.Product using (_×_; proj₁; proj₂) renaming (_,_ to ⟨_,_⟩)
\end{code}

We assume [extensionality][extensionality].
\begin{code}
postulate
  extensionality : ∀ {A B : Set} {f g : A → B} → (∀ (x : A) → f x ≡ g x) → f ≡ g
\end{code}

[extensionality]: Equality/index.html#extensionality


## Streams

Streams are defined in Agda as follows.
\begin{code}
record Stream (A : Set) : Set where
  coinductive
  field
    hd : A
    tl : Stream A

open Stream
\end{code}

A constructor for streams may be defined via *co-pattern matching*.
\begin{code}
infixr 5 _∷_

_∷_ : ∀ {A : Set} → A → Stream A → Stream A
hd (x ∷ xs)  =  x
tl (x ∷ xs)  =  xs
\end{code}

\begin{code}
even : ∀ {A} → Stream A → Stream A
hd (even x) = hd x
tl (even x) = even (tl (tl x))
\end{code}

## Lifting

\begin{code}
record Lift (A : Set) : Set where
  coinductive
  field
    force : A

open Lift
\end{code}

\begin{code}
delay : ∀ {A : Set} → A → Lift A
force (delay x)  =  x
\end{code}

## Alternative definition of stream

\begin{code}
data Stream′ (A : Set) : Set where
  _∷′_ : A → ∞ (Stream′ A) → Stream′ A

hd′ : ∀ {A} → Stream′ A → A
hd′ (x ∷′ xs)  =  x

tl′ : ∀ {A} → Stream′ A → Stream′ A
tl′ (x ∷′ xs)  =  ♭ xs
\end{code}

## Maps between the two definitions

\begin{code}
to : ∀ {A} → Stream A → Stream′ A
to xs = hd xs ∷′ ♯ (to (tl xs))

from : ∀ {A} → Stream′ A → Stream A
hd (from (x ∷′ xs′)) = x
tl (from (x ∷′ xs′)) = from (♭ xs′)
\end{code}

Termination check does not succeed if I replace `∞`, `♯`, `♭` by `Lift`,
`delay`, `force`.

Trying to show full-blown isomorphism appears difficult.

## How to be lazy without even being odd

This is the approach hinted at by Abel in his [lecture].

[lecture]: https://cs.ioc.ee/~tarmo/tsem12/abel-slides.pdf

\begin{code}
record EStream (A : Set) : Set
data OStream (A : Set) : Set

record EStream (A : Set) where
  coinductive
  field
    force : OStream A

open EStream

data OStream (A : Set) where
  cons : A → EStream A → OStream A
\end{code}

Type `OStream` can also include a `nil` clause, if needed.

## Conversions between `Stream` and `EStream`.

\begin{code}
toE : ∀ {A} → Stream A → EStream A
force (toE xs) = cons (hd xs) (toE (tl xs))

fromE : ∀ {A} → EStream A → Stream A
hd (fromE xs′) with force xs′
...               | cons x xs″ = x
tl (fromE xs′) with force xs′
...               | cons x xs″ = fromE xs″

record _∼_ {A : Set} (xs : Stream A) (ys : Stream A) : Set where
  coinductive
  field
    hd-∼ : hd xs ≡ hd ys
    tl-∼ : tl xs ∼ tl ys

open _∼_

record _≈_ {A : Set} (xs′ ys′ : EStream A) : Set
_≋_ : ∀ {A : Set} (xs″ ys″ : OStream A) → Set

record _≈_ {A : Set} (xs′ ys′ : EStream A) where
  coinductive
  field
    force-≈ : force xs′ ≋ force ys′

open _≈_

cons x xs ≋ cons y ys = (x ≡ y) × (xs ≈ ys)

fromE∘toE : ∀ {A} (xs : Stream A) → fromE (toE xs) ∼ xs
hd-∼ (fromE∘toE xs) = refl
tl-∼ (fromE∘toE xs) = fromE∘toE (tl xs)

toE∘fromE : ∀ {A} (xs′ : EStream A) → toE (fromE xs′) ≈ xs′
force-≈ (toE∘fromE xs′) with force xs′
...                        | cons x xs  =  ⟨ refl , toE∘fromE xs ⟩
\end{code}

## Standard Library

Definitions similar to those in this chapter can be found in the standard library.
\begin{code}
\end{code}


## Unicode

This chapter uses the following unicode.

    ∷  U+2237  PROPORTION  (\::)
    ⊗  U+2297  CIRCLED TIMES  (\otimes)
    ∈  U+2208  ELEMENT OF  (\in)
    ∉  U+2209  NOT AN ELEMENT OF  (\inn)