content: module Lets.Data (
    Locality(..)
  , Address(..)
  , Person(..)
  , IntAnd(..)
  , IntOr(..)
  , fredLocality
  , fredAddress
  , fred
  , maryLocality
  , maryAddress
  , mary
  , Store(..)
  , Const (..)
  , Tagged(..)
  , Identity(..)
  , AlongsideLeft(..)
  , AlongsideRight(..)
  ) where
  
  import Control.Applicative(Applicative(..))
  import Data.Monoid(Monoid(..))
  
  data Locality =
    Locality
      String -- city
      String -- state
      String -- country
    deriving (Eq, Show)  
  
  data Address =
    Address
      String -- street
      String -- suburb
      Locality
    deriving (Eq, Show)  
  
  data Person =
    Person
      Int -- age
      String -- name
      Address -- address
    deriving (Eq, Show)
  
  data IntAnd a =
    IntAnd
      Int
      a
    deriving (Eq, Show)
  
  data IntOr a =
    IntOrIs Int
    | IntOrIsNot a
    deriving (Eq, Show)
  
  fredLocality ::
    Locality
  fredLocality =
    Locality
      "Fredmania"
      "New South Fred"
      "Fredalia"
  
  fredAddress ::
    Address
  fredAddress =
    Address
      "15 Fred St"
      "Fredville"
      fredLocality
  
  fred ::
    Person
  fred =
    Person
      24
      "Fred"
      fredAddress
  
  maryLocality ::
    Locality
  maryLocality =
    Locality
      "Mary Mary"
      "Western Mary"
      "Maristan"
  
  maryAddress ::
    Address
  maryAddress =
    Address
      "83 Mary Ln"
      "Maryland"
      maryLocality
  
  mary ::
    Person
  mary =
    Person
      28
      "Mary"
      maryAddress
  
  ----
  
  data Store s a =
    Store
      (s -> a)
      s
  
  data Const a b =
    Const {
      getConst :: 
        a
    }
    deriving (Eq, Show)
  
  instance Functor (Const a) where
    fmap _ (Const a) =
      Const a
  
  instance Monoid a => Applicative (Const a) where
    pure _ =
      Const mempty
    Const f <*> Const a =
      Const (f `mappend` a)
  
  data Tagged a b = 
    Tagged {
      getTagged ::
        b
    }
    deriving (Eq, Show)
  
  instance Functor (Tagged a) where
    fmap f (Tagged b) =
      Tagged (f b)
  
  instance Applicative (Tagged a) where
    pure =
      Tagged
    Tagged f <*> Tagged a =
      Tagged (f a)
  
  data Identity a =
    Identity {
      getIdentity ::
        a
    }
    deriving (Eq, Show)
  
  instance Functor Identity where
    fmap f (Identity a) =
      Identity (f a)
  
  instance Applicative Identity where
    pure =
      Identity
    Identity f <*> Identity a =
      Identity (f a)
  
  data AlongsideLeft f b a =
    AlongsideLeft {
      getAlongsideLeft :: 
        f (a, b)
    }
  
  instance Functor f => Functor (AlongsideLeft f b) where
    fmap f (AlongsideLeft x) =
      AlongsideLeft (fmap (\(a, b) -> (f a, b)) x)
  
  data AlongsideRight f a b =
    AlongsideRight {
      getAlongsideRight ::
        f (a, b)
    }
  
  instance Functor f => Functor (AlongsideRight f a) where
    fmap f (AlongsideRight x) =
      AlongsideRight (fmap (\(a, b) -> (a, f b)) x)
  