{-# LANGUAGE RankNTypes #-}
module Fresnel.Getter
( -- * Getters
  Getter
, IsGetter
  -- * Construction
, to
, getting
  -- * Elimination
, views
, view
, (^.)
) where

import Data.Profunctor
import Data.Profunctor.Unsafe ((#.), (.#))
import Fresnel.Bifunctor.Contravariant
import Fresnel.Getter.Internal (IsGetter)
import Fresnel.Optic

-- Getters

type Getter s a = forall p . IsGetter p => Optic' p s a


-- Construction

to :: (s -> a) -> Getter s a
to :: forall s a. (s -> a) -> Getter s a
to s -> a
f = (s -> a) -> p a s -> p s s
forall a b c. (a -> b) -> p b c -> p a c
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap s -> a
f (p a s -> p s s) -> (p a a -> p a s) -> p a a -> p s s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p a a -> p a s
forall (p :: * -> * -> *) a b c.
(Profunctor p, Bicontravariant p) =>
p a b -> p a c
rphantom


getting :: (Profunctor p, Bicontravariant p) => Optic p s t a b -> Optic' p s a
getting :: forall (p :: * -> * -> *) s t a b.
(Profunctor p, Bicontravariant p) =>
Optic p s t a b -> Optic' p s a
getting Optic p s t a b
l p a a
f = p s t -> p s s
forall (p :: * -> * -> *) a b c.
(Profunctor p, Bicontravariant p) =>
p a b -> p a c
rphantom (p s t -> p s s) -> Optic p s t a b -> p a b -> p s s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic p s t a b
l (p a b -> p s s) -> p a b -> p s s
forall a b. (a -> b) -> a -> b
$ p a a -> p a b
forall (p :: * -> * -> *) a b c.
(Profunctor p, Bicontravariant p) =>
p a b -> p a c
rphantom p a a
f


-- Elimination

views :: Getter s a -> (a -> r) -> (s -> r)
views :: forall s a r. Getter s a -> (a -> r) -> s -> r
views Getter s a
b = Forget r s s -> s -> r
forall {k} r a (b :: k). Forget r a b -> a -> r
runForget (Forget r s s -> s -> r)
-> (Forget r a a -> Forget r s s) -> Forget r a a -> s -> r
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> (a -> b) -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> p a b -> p a c
#. Forget r a a -> Forget r s s
Getter s a
b (Forget r a a -> s -> r)
-> ((a -> r) -> Forget r a a) -> (a -> r) -> s -> r
forall a b c (q :: * -> * -> *).
Coercible b a =>
(b -> c) -> q a b -> a -> c
forall (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
p b c -> q a b -> p a c
.# (a -> r) -> Forget r a a
forall {k} r a (b :: k). (a -> r) -> Forget r a b
Forget

view :: Getter s a -> (s -> a)
view :: forall s a. Getter s a -> s -> a
view Getter s a
b = Getter s a -> (a -> a) -> s -> a
forall s a r. Getter s a -> (a -> r) -> s -> r
views Optic' p s a
Getter s a
b a -> a
forall a. a -> a
id

(^.) :: s -> Getter s a -> a
s
s ^. :: forall s a. s -> Getter s a -> a
^. Getter s a
o = Getter s a -> s -> a
forall s a. Getter s a -> s -> a
view Optic' p s a
Getter s a
o s
s

infixl 8 ^.