{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | This module defines a stream-like type named 'Replicator', which is
-- mainly used in the definition of the 'Data.Unrestricted.Linear.Dupable'
-- class to provide efficient linear duplication.
-- The API of 'Replicator' is close to the one of an infinite stream: it
-- can either produce a new value linearly (with 'next' or 'next#'), or be
-- linearly discarded (with 'consume' or 'extract').
--
-- A crucial aspect, from a performance standpoint, is that the 'pure' function
-- (which takes an unrestricted argument) is implemented efficiently: the
-- 'Replicator' returns /the same/ value on each call to 'next'. That is, the
-- pointer is always shared. This will allow 'Data.Unrestricted.Linear.Movable'
-- types to be given an efficient instance of 'Data.Unrestricted.Linear.Dupable'.
-- Instances of both 'Data.Unrestricted.Linear.Movable' and
-- 'Data.Unrestricted.Linear.Dupable' typically involve deep copies. The
-- implementation of 'pure' lets us make sure that, for @Movable@ types, only one
-- deep copy is performed, rather than one per additional replica.
--
-- Strictly speaking, the implementation of '(<*>)' plays a role in all this as
-- well:
-- For two 'pure' 'Replicators' @fs@ and @as@, @fs \<*\> as@  is a pure
-- 'Replicator'. Together, 'pure' and '(<*>)' form the
-- 'Data.Functor.Linear.Applicative' instance of 'Replicator'.
module Data.Replicator.Linear
  ( Replicator,
    consume,
    duplicate,
    map,
    pure,
    (<*>),
    next,
    next#,
    take,
    extract,
    extend,
    Elim,
    elim,
  )
where

import Data.Replicator.Linear.Internal
import Data.Replicator.Linear.Internal.Instances ()