Copyright | (c) Sophie Hirn, 2018 |
---|---|

License | BSD2 |

Maintainer | sophie.hirn@wyvernscale.com |

Safe Haskell | Safe |

Language | Haskell2010 |

Some helpers to make using Prelude.filter and similar value selection a bit easier. Includes combinators for predicates as well as an operator to match the constructor used for the given value.

- constrName :: (HasConstructor (Rep a), Generic a) => a -> String
- class HasConstructor f where
- class ReduceWith a where
- class (HasConstructor (Rep c), Generic c) => Reduce a c | a -> c where
- (=?=) :: (Reduce a c, Reduce b c) => a -> b -> Bool
- (==>) :: (a -> Bool) -> (a -> b) -> a -> Maybe b
- (<||>) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
- any_ :: [a -> Bool] -> a -> Bool
- (<&&>) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
- all_ :: [a -> Bool] -> a -> Bool
- data Infinite a
- mapMaybe :: (a -> Maybe b) -> [a] -> [b]

# Constructors

The `(=?=)`

-operator can be used to check whether two values were
generated using the same constructor. For this to work, the
underlying data type must instantiate `Generic`

,
parameters to the constructor can additionally be left out if their
type implements `ReduceWith`

.

constrName :: (HasConstructor (Rep a), Generic a) => a -> String Source #

Retrieve the constructor name of the given value as a string. This implementation is taken from https://stackoverflow.com/questions/48179380/getting-the-data-constructor-name-as-a-string-using-ghc-generics .

class HasConstructor f where Source #

Automatically derived from `Generic`

instances.

genericConstrName :: f x -> String Source #

(HasConstructor x, HasConstructor y) => HasConstructor ((:+:) x y) Source # | |

HasConstructor f => HasConstructor (D1 c f) Source # | |

Constructor Meta c => HasConstructor (C1 c f) Source # | |

# Reduction

Constructors can be *reduced* to values by passing them arbitrary
arguments. The actual value of those does not impact the result of
the `(=?=)`

-operator. For lazy members, passing `undefined`

works
just fine, but putting `undefined`

into strict fields causes carnage.
`ReduceWith`

provides arbitrary values, deriving from `Default`

where
possible.

class ReduceWith a where Source #

Type that can be reduced away from a constructor. Use this to make your
data types compatible. The reduction process and the `(=?=)`

-operator do
not evaluate fields, therefore creating an empty instance which defaults to

is okay `reduceWith`

= `undefined`

**as long as no reduced field of**
**this type is strict**.

reduceWith :: a Source #

ReduceWith Bool Source # | |

ReduceWith Char Source # | |

Default a => ReduceWith a Source # | |

class (HasConstructor (Rep c), Generic c) => Reduce a c | a -> c where Source #

Reduction of a constructor `a -> ... -> c`

to a value of type `c`

.

# Operators

(=?=) :: (Reduce a c, Reduce b c) => a -> b -> Bool infixl 4 Source #

Checks whether two values are created by the same data constructor. Also works with constructors that have not yet received all their arguments. This allows for very convenient constructs, e.g.:

`>>>`

True`Just 1 =?= Just`

`>>>`

False`Just 1 =?= Nothing`

`>>>`

`let filterJust = filter (=?= Just)`

`>>>`

[Just 1, Just 9001]`filterJust [Just 1, Nothing, Just 9001]`

`>>>`

`let filterJust_ = mapMaybe $ (=?= Just) ==> fromJust`

`>>>`

[1, 9001]`filterJust_ [Just 1, Nothing, Just 9001]`

`>>>`

`let over9000 = mapMaybe $ ((=?= Just) <&&> (>9000) . fromJust) ==> fromJust`

`>>>`

[9001]`over9000 [Just 1, Nothing, Just 9001]`

# Matching Wrappers

Adds negative and positive infinity to an ordered type. The `fromEnum`

function is inherently susceptible to overflow since the class `Enum`

is
defined using `Int`

instead of `Integer`

, but this should not cause trouble
with "small" enums.

Functor Infinite Source # | |

(Eq a, Bounded a, Enum a) => Enum (Infinite a) Source # | |

Eq a => Eq (Infinite a) Source # | |

Ord a => Ord (Infinite a) Source # | |

Read a => Read (Infinite a) Source # | |

Show a => Show (Infinite a) Source # | |

Generic (Infinite a) Source # | |

Default a => Default (Infinite a) Source # | |

type Rep (Infinite a) Source # | |

# Useful functions from other modules

mapMaybe :: (a -> Maybe b) -> [a] -> [b] #

The `mapMaybe`

function is a version of `map`

which can throw
out elements. In particular, the functional argument returns
something of type

. If this is `Maybe`

b`Nothing`

, no element
is added on to the result list. If it is

, then `Just`

b`b`

is
included in the result list.

#### Examples

Using

is a shortcut for `mapMaybe`

f x

in most cases:`catMaybes`

$ `map`

f x

`>>>`

`import Text.Read ( readMaybe )`

`>>>`

`let readMaybeInt = readMaybe :: String -> Maybe Int`

`>>>`

[1,3]`mapMaybe readMaybeInt ["1", "Foo", "3"]`

`>>>`

[1,3]`catMaybes $ map readMaybeInt ["1", "Foo", "3"]`

If we map the `Just`

constructor, the entire list should be returned:

`>>>`

[1,2,3]`mapMaybe Just [1,2,3]`