Safe Haskell | Safe |
---|---|

Language | Haskell2010 |

The `Newtype`

typeclass and related functions.
Primarily pulled from Conor McBride's Epigram work. Some examples:

`>>>`

10`ala Sum foldMap [1,2,3,4]`

`>>>`

8`ala Endo foldMap [(+1), (+2), (subtract 1), (*2)] 3`

`>>>`

1`under2 Min (<>) 2 1`

`>>>`

All {getAll = True)`over All not (All False)`

This package includes `Newtype`

instances for all the (non-GHC/foreign)
newtypes in base (as seen in the examples).
However, there are neat things you can do with this with
*any* newtype and you should definitely define your own `Newtype`

instances for the power of this library.
For example, see `ala Cont traverse`

, with the proper `Newtype`

instance for Cont.
You can easily define new instances for your newtypes with the help of GHC.Generics

import GHC.Generics (...) newtype Example = Example Int deriving (Generic) instance Newtype Example

This avoids the use of Template Haskell (TH) to get new instances.

## Synopsis

- class Newtype n where
- op :: (Newtype n, o ~ O n) => (o -> n) -> n -> o
- ala :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> ((o -> n) -> b -> n') -> b -> o'
- ala' :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> b -> o'
- under :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (n -> n') -> o -> o'
- over :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (o -> o') -> n -> n'
- under2 :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (n -> n -> n') -> o -> o -> o'
- over2 :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (o -> o -> o') -> n -> n -> n'
- underF :: (Newtype n, Newtype n', o' ~ O n', o ~ O n, Functor f, Functor g) => (o -> n) -> (f n -> g n') -> f o -> g o'
- overF :: (Newtype n, Newtype n', o' ~ O n', o ~ O n, Functor f, Functor g) => (o -> n) -> (f o -> g o') -> f n -> g n'

# Documentation

As long as the type `n`

is an instance of Generic, you can create an instance
with just `instance Newtype n`

Nothing

pack :: (Generic n, GNewtype (Rep n), O n ~ GO (Rep n)) => O n -> n #

unpack :: (Generic n, GNewtype (Rep n), O n ~ GO (Rep n)) => n -> O n #

## Instances

op :: (Newtype n, o ~ O n) => (o -> n) -> n -> o #

This function serves two purposes:

- Giving you the unpack of a newtype without you needing to remember the name.
- Showing that the first parameter is
*completely ignored*on the value level, meaning the only reason you pass in the constructor is to provide type information. Typeclasses sure are neat.

`>>>`

3`op Identity (Identity 3)`

ala :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> ((o -> n) -> b -> n') -> b -> o' #

The workhorse of the package. Given a "packer" and a "higher order function" (*hof*),
it handles the packing and unpacking, and just sends you back a regular old
function, with the type varying based on the *hof* you passed.

The reason for the signature of the *hof* is due to `ala`

not caring about structure.
To illustrate why this is important, consider this alternative implementation of `under2`

:

under2 :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (n -> n -> n') -> (o -> o -> o') under2' pa f o0 o1 = ala pa (\p -> uncurry f . bimap p p) (o0, o1)

Being handed the "packer", the *hof* may apply it in any structure of its choosing –
in this case a tuple.

`>>>`

10`ala Sum foldMap [1,2,3,4]`

ala' :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> b -> o' #

This is the original function seen in Conor McBride's work.
The way it differs from the `ala`

function in this package,
is that it provides an extra hook into the "packer" passed to the hof.
However, this normally ends up being `id`

, so `ala`

wraps this function and
passes `id`

as the final parameter by default.
If you want the convenience of being able to hook right into the hof,
you may use this function.

`>>>`

10`ala' Sum foldMap length ["hello", "world"]`

`>>>`

Just 42`ala' First foldMap (readMaybe @Int) ["x", "42", "1"]`

under :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (n -> n') -> o -> o' #

A very simple operation involving running the function 'under' the newtype.

`>>>`

27`under Product (stimes 3) 3`

over :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (o -> o') -> n -> n' #

The opposite of `under`

. I.e., take a function which works on the
underlying types, and switch it to a function that works on the newtypes.

`>>>`

All {getAll = True}`over All not (All False)`

under2 :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (n -> n -> n') -> o -> o -> o' #

Lower a binary function to operate on the underlying values.

`>>>`

True`under2 Any (<>) True False`

*Since: 0.5.2*

over2 :: (Newtype n, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (o -> o -> o') -> n -> n -> n' #

The opposite of `under2`

.

*Since: 0.5.2*