module Haskell.Prim.Applicative where
open import Haskell.Prim
open import Haskell.Prim.Either
open import Haskell.Prim.Foldable
open import Haskell.Prim.Functor
open import Haskell.Prim.IO
open import Haskell.Prim.List
open import Haskell.Prim.Maybe
open import Haskell.Prim.Monoid
open import Haskell.Prim.Tuple
record Applicative (f : Set → Set) : Set₁ where
  infixl 4 _<*>_ _<*_ _*>_
  field
    pure  : a → f a
    _<*>_ : f (a → b) → f a → f b
    overlap ⦃ super ⦄ : Functor f
    _<*_ : f a → f b → f a
    _*>_ : f a → f b → f b
record DefaultApplicative (f : Set → Set) : Set₁ where
  constructor mk
  infixl 4 _<*>_ _<*_ _*>_
  field
    pure  : a → f a
    _<*>_ : f (a → b) → f a → f b
    overlap ⦃ super ⦄ : Functor f
  _<*_ : f a → f b → f a
  x <* y = const <$> x <*> y
  _*>_ : f a → f b → f b
  x *> y = const id <$> x <*> y
open Applicative ⦃...⦄ public
{-# COMPILE AGDA2HS Applicative existing-class #-}
private
  mkApplicative : DefaultApplicative t → Applicative t
  mkApplicative x = record {DefaultApplicative x}
instance
  open DefaultApplicative
  iApplicativeList : Applicative List
  iApplicativeList = mkApplicative λ where
    .pure x      → x ∷ []
    ._<*>_ fs xs → concatMap (λ f → map f xs) fs
  iApplicativeMaybe : Applicative Maybe
  iApplicativeMaybe = mkApplicative λ where
    .pure → Just
    ._<*>_ (Just f) (Just x) → Just (f x)
    ._<*>_ _        _        → Nothing
  iApplicativeEither : Applicative (Either a)
  iApplicativeEither = mkApplicative λ where
    .pure → Right
    ._<*>_ (Right f) (Right x) → Right (f x)
    ._<*>_ (Left e)  _         → Left e
    ._<*>_ _         (Left e)  → Left e
  iApplicativeFun : Applicative (λ b → a → b)
  iApplicativeFun = mkApplicative λ where
    .pure        → const
    ._<*>_ f g x → f x (g x)
  iApplicativeTuple₂ : ⦃ Monoid a ⦄ → Applicative (a ×_)
  iApplicativeTuple₂ = mkApplicative λ where
    .pure x                → mempty , x
    ._<*>_ (a , f) (b , x) → a <> b , f x
  iApplicativeTuple₃ : ⦃ Monoid a ⦄ → ⦃ Monoid b ⦄ → Applicative (a × b ×_)
  iApplicativeTuple₃ = mkApplicative λ where
    .pure x                → mempty , mempty , x
    ._<*>_ (a , u , f) (b , v , x) → a <> b , u <> v , f x
instance postulate iApplicativeIO : Applicative IO