-- |
-- Module: Optics.Getter
-- Description: A function considered as an 'Optic'.
--
-- A 'Getter' is simply a function considered as an 'Optic'.
--
-- Given a function @f :: S -> A@, we can convert it into a
-- @'Getter' S A@ using 'to', and convert back to a function using 'view'.
--
-- This is typically useful not when you have functions/'Getter's
-- alone, but when you are composing multiple 'Optic's to produce a
-- 'Getter'.
--
module Optics.Getter
  (
  -- * Formation
   Getter

  -- * Introduction
  , to

  -- * Elimination
  , view
  , views

  -- * Computation
  -- |
  --
  -- @
  -- 'view' ('to' f) ≡ f
  -- @

  -- * Well-formedness
  -- | A 'Getter' is not subject to any laws.

  -- * Subtyping
  , A_Getter
  -- | <<diagrams/Getter.png Getter in the optics hierarchy>>
  )
  where

import Data.Profunctor.Indexed

import Optics.Internal.Bi
import Optics.Internal.Optic

-- | Type synonym for a getter.
type Getter s a = Optic' A_Getter NoIx s a

-- | View the value pointed to by a getter.
--
-- If you want to 'view' a type-modifying optic that is insufficiently
-- polymorphic to be type-preserving, use 'Optics.ReadOnly.getting'.
--
view :: Is k A_Getter => Optic' k is s a -> s -> a
view :: Optic' k is s a -> s -> a
view Optic' k is s a
o = Optic' k is s a -> (a -> a) -> s -> a
forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (a :: OpticKind) (r :: OpticKind).
Is k A_Getter =>
Optic' k is s a -> (a -> r) -> s -> r
views Optic' k is s a
o a -> a
forall (a :: OpticKind). a -> a
id
{-# INLINE view #-}

-- | View the function of the value pointed to by a getter.
views :: Is k A_Getter => Optic' k is s a -> (a -> r) -> s -> r
views :: Optic' k is s a -> (a -> r) -> s -> r
views Optic' k is s a
o = \a -> r
f -> Forget r (Curry is Any) s s -> s -> r
forall (r :: OpticKind) (i :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Forget r i a b -> a -> r
runForget (Forget r (Curry is Any) s s -> s -> r)
-> Forget r (Curry is Any) s s -> s -> r
forall (a :: OpticKind) b. (a -> b) -> a -> b
$ Optic A_Getter is s s a a
-> Optic__ (Forget r) Any (Curry is Any) s s a a
forall (p :: OpticKind -> OpticKind -> OpticKind -> OpticKind)
       (k :: OpticKind) (is :: IxList) (s :: OpticKind) (t :: OpticKind)
       (a :: OpticKind) (b :: OpticKind) (i :: OpticKind).
Profunctor p =>
Optic k is s t a b -> Optic_ k p i (Curry is i) s t a b
getOptic (Optic' k is s a -> Optic A_Getter is s s a a
forall (destKind :: OpticKind) (srcKind :: OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Getter Optic' k is s a
o) ((a -> r) -> Forget r Any a a
forall (r :: OpticKind) (i :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(a -> r) -> Forget r i a b
Forget a -> r
f)
{-# INLINE views #-}

-- | Build a getter from a function.
to :: (s -> a) -> Getter s a
to :: (s -> a) -> Getter s a
to s -> a
f = (forall (p :: OpticKind -> OpticKind -> OpticKind -> OpticKind)
        (i :: OpticKind).
 Profunctor p =>
 Optic_ A_Getter p i (Curry NoIx i) s s a a)
-> Getter s a
forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (t :: OpticKind) (a :: OpticKind) (b :: OpticKind).
(forall (p :: OpticKind -> OpticKind -> OpticKind -> OpticKind)
        (i :: OpticKind).
 Profunctor p =>
 Optic_ k p i (Curry is i) s t a b)
-> Optic k is s t a b
Optic ((s -> a) -> p i a s -> p i s s
forall (p :: OpticKind -> OpticKind -> OpticKind -> OpticKind)
       (a :: OpticKind) (b :: OpticKind) (i :: OpticKind)
       (c :: OpticKind).
Profunctor p =>
(a -> b) -> p i b c -> p i a c
lmap s -> a
f (p i a s -> p i s s) -> (p i a a -> p i a s) -> p i a a -> p i s s
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. p i a a -> p i a s
forall (p :: OpticKind -> OpticKind -> OpticKind -> OpticKind)
       (i :: OpticKind) (c :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(Profunctor p, Bicontravariant p) =>
p i c a -> p i c b
rphantom)
{-# INLINE to #-}