content: {-# LANGUAGE FlexibleInstances      #-}
  {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE TypeFamilies           #-}
  -- | Interface to access portions of a larger data structure.
  --
  -- Default operations to access elements from structs and arrays (e.g., a field
  -- of a struct, an element of an array) allow obtaining the values of those
  -- elements, but not modifying.
  --
  -- This module defines a common interface to manipulate portions of a larger
  -- data structure. We define the interface in a generic way, using a type
  -- class with two operations: one to set the value of the sub-element, and
  -- one to update the value of such element applying a stream function.
  module Copilot.Language.Operators.Projection
      ( Projectable (..) )
    where
  
  import Copilot.Language.Stream (Stream)
  
  infixl 8 =:
  infixl 8 =$
  
  -- | Common interface to manipulate portions of a larger data structure.
  --
  -- A projectable d s t means that it is possible to manipulate a sub-element s
  -- of type t carried in a stream of type d.
  class Projectable d s t | d s -> t where
  
    -- | Unapplied projection or element access on a type.
    data Projection d s t
  
    -- | Modify the value of a sub-element of a type in a stream of elements
    -- of that type.
    (=:) :: Projection d s t -> Stream t -> Stream d
  
    -- | Update the value of a sub-element of a type in a stream of elements of
    -- that type, by applying a function on streams.
    (=$) :: Projection d s t -> (Stream t -> Stream t) -> Stream d
  