| -- | |
| -- Module : Data.Stream |
| -- Copyright : (c) Data61 2018-2019 |
| -- Commonwealth Science and Research Organisation (CSIRO) |
| -- ABN 41 687 119 230 |
| -- License : BSD3 |
| -- |
| -- This module provides a type for /streams/ (infinite lists), along with a handful of "Data.List" |
| -- style utility functions. |
| -- |
| -- It expects to be imported qualified, except for operators and type names. |
| -- |
| -- > import Data.Stream (Stream, (!)) |
| -- > import qualified Data.Stream as S |
| {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} |
| module Data.Stream |
| ( -- * Type and Constructors |
| Stream (..) |
| , -- * Eliminators |
| head |
| , tail |
| , -- * Indexing |
| take |
| , drop |
| , (!) |
| -- * Making Streams |
| , fromList |
| , naturals |
| ) where |
| |
| import Prelude hiding (take, drop, head, tail) |
| import Data.Foldable (toList) |
| |
| import qualified Data.List as L |
| |
| -- | A stream is an infinite list of values. It is a list without the nil @[]@ constructor. |
| -- Thus, all values of type @Stream a@ must either cycle or continuously produce new values |
| -- using laziness. |
| -- |
| -- Thus a @Stream a@ could be thought of as a corecursive process that eternaly produces |
| -- @a@ values. |
| -- |
| -- Because of the 'Functor', 'Foldable', and 'Traversable' instances, many utility |
| -- functions can be found in those classes also (in particular the useful 'toList'). |
| -- |
| data Stream a = Cons a (Stream a) deriving (Show, Functor, Foldable, Traversable) |
| |
| -- | Implemented like a zip-list. That is, @pure x@ is |
| -- an infinite stream of @x@ repeated over and over, and @fs \<*> xs@ consists of |
| -- each function in @fs@ applied to the corresponding argument in @xs@. |
| instance Applicative Stream where |
| |
| pure x = Cons x (pure x) |
| |
| (Cons f fs) <*> (Cons x xs) = Cons (f x) (fs <*> xs) |
| |
| -- | Analogous to 'Data.List.take' from Data.List, returns a list containing the first @n@ elements |
| -- of the given stream. |
| take :: Int -> Stream a -> [a] |
| take n = L.take n . toList |
| |
| -- | Analogous to 'Data.List.take' from Data.List, returns the given stream but without the first |
| -- @n@ elements. |
| drop :: Int -> Stream a -> Stream a |
| drop 0 s = s |
| drop n (Cons _ xs) = drop (n - 1) xs |
| |
| -- | Returns the first element of the stream. |
| head :: Stream a -> a |
| head (Cons x xs) = x |
| |
| -- | Returns the stream without the first element. |
| tail :: Stream a -> Stream a |
| tail (Cons x xs) = xs |
| |
| -- | A stream starting at zero and incrementing by one from there. |
| naturals :: Stream Integer |
| naturals = Cons 0 (fmap succ naturals) |
| |
| -- | A stream consisting of all the elements of the given list @xs@ in order. |
| -- |
| -- If @xs@ is finite, then the stream will cycle forever through those elements, |
| -- i.e. @fromList (cycle xs) == fromList xs@ (where @==@ is a bisimulation equivalence). |
| fromList :: [a] -> Stream a |
| fromList xs = go xs |
| where |
| go [] = go xs |
| go (a:as) = Cons a (fromList as) |
| |
| -- | An operator to return the @n@th element of a stream. |
| (!) :: Stream a -> Int -> a |
| s ! x = head (drop x s) |