{-# 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 -- 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 ---------------------------------------------------------------