between-0.11.0.0: src/Data/Function/Between/Types.hs
{-# LANGUAGE NoImplicitPrelude #-}
-- |
-- Module: $HEADER$
-- Description: Precursors to Iso, Lens and Prism types.
-- Copyright: (c) 2015, Peter Trško
-- License: BSD3
--
-- Maintainer: peter.trsko@gmail.com
-- Stability: experimental
-- Portability: NoImplicitPrelude
--
-- This module defines types that behave as a precursors to types defined in
-- <https://hackage.haskell.org/package/lens lens> library.
--
-- /Since version 0.11.0.0./
module Data.Function.Between.Types
(
-- * PreIso
PreIso
, PreIso'
-- * PreLens
, PreLens
, PreLens'
-- * PrePrism
, PrePrism
, PrePrism'
)
where
import Data.Either (Either)
-- {{{ PreIso -----------------------------------------------------------------
-- | Family of types that can construct isomorphism between types.
--
-- /Since version 0.11.0.0./
type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r
-- | A simple 'PreIso'.
--
-- /Since version 0.11.0.0./
type PreIso' r s a = PreIso r s s a a
-- }}} PreIso -----------------------------------------------------------------
-- {{{ PreLens ----------------------------------------------------------------
-- | We can also view 'PreLens' as a special kind of 'PreIso':
--
-- @
-- 'PreLens' r s t a b = 'PreIso' r s (s -> t) a b
-- @
--
-- /Since version 0.11.0.0./
type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r
-- | A simple 'PreLens', where we can not change the type of the information
-- we are focusing on. As a consequence neither the type of the container data
-- type can be changed.
--
-- /Since version 0.11.0.0./
type PreLens' r s a = PreLens r s s a a
-- }}} PreLens ----------------------------------------------------------------
-- {{{ PrePrism ---------------------------------------------------------------
-- | We can also get 'PrePrism' by specializing 'PreIso':
--
-- @
-- 'PrePrism' r s t a b = 'PreIso' r s t ('Either' t a) b
-- @
--
-- This fact is not surprising, since /Prisms/ are actually a special case of
-- isomorphism between two types.
--
-- Let's have a type @s@, and we want to extract specific information out of
-- it, but that information may not be there. Because of the fact that the type
-- @s@ can be a sum type. Imagine e.g. standard 'Maybe' data type:
--
-- @
-- 'Maybe' a = 'Data.Maybe.Nothing' | 'Data.Maybe.Just' a
-- @
--
-- How do we create something that can extrat that information from a sum type,
-- and if necessary, also reconstructs that sum type. The answer is /Prism/,
-- which is defined as an isomorphism between that type @s@ and @'Either' t a@
-- where @a@ is the information we want to extract and @t@ is the rest that we
-- don't care about.
--
-- You may have noticed, that definition of 'PrePrism' contains some type
-- variables that aren't mentioned in the above definition. The reason for this
-- is that, as with /Lenses/ we may want to extract value of type @a@, but when
-- constructing new data type we may want to change the type of that value in
-- to @b@ and therefore type @s@ may not fit, which is the reason why we have
-- type @t@ in there. Once again we can ilustrate this with 'Maybe'. Lets say
-- that we have a value of @s = 'Maybe' a@, but if we change the type of @a@ in
-- to @b@, and try to create 'Maybe' again, then it would have type @'Maybe' b
-- = t@.
--
-- /Since version 0.11.0.0./
type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r
-- | A simple 'PrePrism', where we can not change the type of the information
-- we are focusing on. As a consequence neither the type of the container data
-- type can be changed.
--
-- If we define 'PrePrism'' in terms of 'PreIso'' then we have even better
-- ilustration of /Prism/ concept in terms of isomorphism:
--
-- @
-- 'PrePrism'' r s a = 'PreIso'' r s ('Either' t a)
-- @
--
-- /Since version 0.11.0.0./
type PrePrism' r s a = PrePrism r s s a a
-- }}} PrePrism ---------------------------------------------------------------