There are several possibilities.
Using the Data.Stream
module you can define an infinite sequence 1 2 3 1 2 3 1 2 3 ...
like this:
open import Data.Stream
open import Coinduction
stream : Stream ℕ
stream = 1 ∷ ♯ (2 ∷ ♯ (3 ∷ ♯ stream))
Using the Data.Colist
module you can define both finite and infinite sequences:
open import Data.Colist
open import Coinduction
colist-fin : Colist ℕ
colist-fin = 1 ∷ ♯ (2 ∷ ♯ (3 ∷ ♯ []))
colist-inf : Colist ℕ
colist-inf = 1 ∷ ♯ (2 ∷ ♯ (3 ∷ ♯ colist-inf))
And you can also define the Stream
datatype as a coinductive record:
{-# OPTIONS --copatterns #-}
record Stream {α} (A : Set α) : Set α where
coinductive
constructor _∷_
field
head : A
tail : Stream A
open Stream
zeros : Stream ℕ
head zeros = 0
tail zeros = zeros
However copatterns do not play well with the rest of Agda (taken from release notes):
Copatterns are yet experimental and the following does not work:
* Copatterns and 'with' clauses.
* Compilation of copatterns to Haskell, JS, or Epic.
* Projections generated by
open R {{...}}
are not handled properly on lhss yet.
* Conversion checking is slower in the presence of copatterns,
since stuck definitions of record type do no longer count
as neutral, since they can become unstuck by applying a projection.
Thus, comparing two neutrals currently requires comparing all
they projections, which repeats a lot of work.