{-# OPTIONS --without-K --safe #-}
module Prelude.Function where

open import Agda.Primitive

private variable
  a b c : Level
  A B   : Set a

infixr 9 _∘_ -- _∘₂_
--infixl 8 _ˢ_
--infixl 0 _|>_
infix  0 case_of_ case_return_of_
infixr -100 _$_

id : A  A
id x = x

const : A  (B  A)
const a = λ _  a

constω : {A : Setω} {B : Set b}  A  (B  A)
constω a = λ _  a

infix -10 idFun
idFun : (A : Set a)  A  A
idFun A x = x

-- syntax idFun A x = x of A
syntax idFun A x = x  A

infix -10 idFunω
idFunω : (A : Setω)  A  A
idFunω A x = x

syntax idFunω A x = x ⦂ω A

flip :  {A : Set a} {B : Set b} {C : A  B  Set c} 
       ((x : A) (y : B)  C x y)  ((y : B) (x : A)  C x y)
flip f = λ y x  f x y
{-# INLINE flip #-}

_∘_ : {B : A  Set b} {C : {x : A}  B x  Set c} 
      (∀ {x} (y : B x)  C y)  (g : (x : A)  B x) 
      ((x : A)  C (g x))
f  g = λ x  f (g x)
{-# INLINE _∘_ #-}

_$_ : {B : A  Set b} 
      ((x : A)  B x)  ((x : A)  B x)
f $ x = f x
{-# INLINE _$_ #-}

_$ₕ_ : {B : A  Set b} 
      ({x : A}  B x)  ((x : A)  B x)
f $ₕ x = f {x}
{-# INLINE _$_ #-}

_$ᵢ_ : {B : A  Set b} 
      (⦃ x : A   B x)  ((x : A)  B x)
f $ᵢ x = f  x 
{-# INLINE _$_ #-}

case_return_of_ :  {A : Set a} (x : A) (B : A  Set b) 
                  ((x : A)  B x)  B x
case x return B of f = f x
{-# INLINE case_return_of_ #-}

case_of_ : {B : Set b}
   A  (A  B)  B
case x of f = case x return _ of f
{-# INLINE case_of_ #-}

-- Conversely it is sometimes useful to be able to extract the
-- type of a given expression.

typeOf : {A : Set a}  A  Set a
typeOf {A = A} _ = A

it :  {} {A : Set }   A   A
it  a  = a

itω : {A : Setω}   A   A
itω  a  = a