smash-0.1.3: Combinators for Maybe types
Copyright (c) 2020-2022 Emily Pillmore BSD-3-Clause Emily Pillmore Experimental CPP, RankNTypes, TypeApplications Safe Haskell2010

Data.Can

Description

This module contains the definition for the Can datatype. In practice, this type is isomorphic to Maybe These - the type with two possibly non-exclusive values and an empty case.

Synopsis

# Datatypes

Categorically, the Can datatype represents the pointed product in the category Hask* of pointed Hask types. The category Hask* consists of Hask types affixed with a dedicated base point of an object along with the object - i.e. Maybe a in Hask. Hence, the product is (1 + a) * (1 + b) ~ 1 + a + b + a*b, or Maybe (These a b) in Hask. Pictorially, you can visualize this as:

Can:
a
|
Non +---+---+ (a,b)
|
b


The fact that we can think about Can as your average product gives us some reasoning power about how this thing will be able to interact with the coproduct in Hask*, called Wedge. Namely, facts about currying Can a b -> c ~ a -> b -> c and distributivity over Wedge along with other facts about its associativity, commutativity, and any other analogy with (',') that you can think of.

data Can a b Source #

The Can data type represents values with two non-exclusive possibilities, as well as an empty case. This is a product of pointed types - i.e. of Maybe values. The result is a type, Can a b, which is isomorphic to Maybe (These a b).

Constructors

 Non One a Eno b Two a b

#### Instances

Instances details

## Type synonyms

type (⊗) a b = Can a b Source #

A type operator synonym for Can

# Combinators

canFst :: Can a b -> Maybe a Source #

Project the left value of a Can datatype. This is analogous to fst for (',').

canSnd :: Can a b -> Maybe b Source #

Project the right value of a Can datatype. This is analogous to snd for (',').

isOne :: Can a b -> Bool Source #

Detect if a Can is a One case.

isEno :: Can a b -> Bool Source #

Detect if a Can is a Eno case.

isTwo :: Can a b -> Bool Source #

Detect if a Can is a Two case.

isNon :: Can a b -> Bool Source #

Detect if a Can is a Non case.

## Eliminators

Arguments

 :: c default value to supply for the Non case -> (a -> c) eliminator for the One case -> (b -> c) eliminator for the Eno case -> (a -> b -> c) eliminator for the Two case -> Can a b -> c

Case elimination for the Can datatype

Arguments

 :: c default value to supply for the Non case -> (a -> c) eliminator for the One case -> (b -> c) eliminator for the Eno case -> (c -> c -> c) merger for the Two case -> Can a b -> c

Case elimination for the Can datatype, with uniform behaviour.

Arguments

 :: Monoid c => (a -> c) eliminator for the One case -> (b -> c) eliminator for the Eno case -> Can a b -> c

Case elimination for the Can datatype, with uniform behaviour over a Monoid result.

Arguments

 :: Applicative m => Monoid c => (a -> m c) eliminator for the One case -> (b -> m c) eliminator for the Eno case -> Can a b -> m c

Case elimination for the Can datatype, with uniform behaviour over a Monoid result in the context of an Applicative.

# Folding and Unfolding

foldOnes :: Foldable f => (a -> m -> m) -> m -> f (Can a b) -> m Source #

Fold over the One cases of a Foldable of Cans by some accumulating function.

foldEnos :: Foldable f => (b -> m -> m) -> m -> f (Can a b) -> m Source #

Fold over the Eno cases of a Foldable of Cans by some accumulating function.

foldTwos :: Foldable f => (a -> b -> m -> m) -> m -> f (Can a b) -> m Source #

Fold over the Two cases of a Foldable of Cans by some accumulating function.

gatherCans :: Can [a] [b] -> [Can a b] Source #

Gather a Can of two lists and produce a list of Can values, mapping the Non case to the empty list, One' case to a list of Ones, the Eno case to a list of Enos, or zipping Two along both lists.

unfoldr :: Alternative f => (b -> Can a b) -> b -> f a Source #

Unfold from right to left into a pointed product. For a variant that accumulates in the seed instead of just updating with a new value, see accumUntil and accumUntilM.

unfoldrM :: (Monad m, Alternative f) => (b -> m (Can a b)) -> b -> m (f a) Source #

Unfold from right to left into a monadic computation over a pointed product

iterateUntil :: Alternative f => (b -> Can a b) -> b -> f a Source #

Iterate on a seed, accumulating a result. See iterateUntilM for more details.

iterateUntilM :: Monad m => Alternative f => (b -> m (Can a b)) -> b -> m (f a) Source #

Iterate on a seed, which may result in one of four scenarios:

1. The function yields a Non value, which terminates the iteration.
2. The function yields a One value.
3. The function yields a Eno value, which changes the seed and iteration continues with the new seed.
4. The function yields the a value of a Two case.

accumUntil :: Alternative f => Monoid b => (b -> Can a b) -> f a Source #

Iterate on a seed, accumulating values and monoidally updating the seed with each update.

accumUntilM :: Monad m => Alternative f => Monoid b => (b -> m (Can a b)) -> m (f a) Source #

Iterate on a seed, accumulating values and monoidally updating a seed within a monad.

# Filtering

ones :: Foldable f => f (Can a b) -> [a] Source #

Given a Foldable of Cans, collect the values of the One cases, if any.

enos :: Foldable f => f (Can a b) -> [b] Source #

Given a Foldable of Cans, collect the values of the Eno cases, if any.

twos :: Foldable f => f (Can a b) -> [(a, b)] Source #

Given a Foldable of Cans, collect the values of the Two cases, if any.

filterOnes :: Foldable f => f (Can a b) -> [Can a b] Source #

Filter the One cases of a Foldable of Can values.

filterEnos :: Foldable f => f (Can a b) -> [Can a b] Source #

Filter the Eno cases of a Foldable of Can values.

filterTwos :: Foldable f => f (Can a b) -> [Can a b] Source #

Filter the Two cases of a Foldable of Can values.

filterNons :: Foldable f => f (Can a b) -> [Can a b] Source #

Filter the Non cases of a Foldable of Can values.

# Curry & Uncurry

canCurry :: (Can a b -> Maybe c) -> Maybe a -> Maybe b -> Maybe c Source #

Curry a function from a Can to a Maybe value, resulting in a function of curried Maybe values. This is analogous to currying for (->).

canUncurry :: (Maybe a -> Maybe b -> Maybe c) -> Can a b -> Maybe c Source #

Uncurry a function from a Can to a Maybe value, resulting in a function of curried Maybe values. This is analogous to uncurrying for (->).

# Partitioning

partitionCans :: Alternative f => Foldable t => t (Can a b) -> (f a, f b) Source #

Given a Foldable of Cans, partition it into a tuple of alternatives their parts.

partitionAll :: Foldable f => f (Can a b) -> ([a], [b], [(a, b)]) Source #

Partition a list of Can values into a triple of lists of all of their constituent parts

partitionEithers :: Foldable f => f (Either a b) -> Can [a] [b] Source #

Partition a list of Either values, separating them into a Can value of lists of left and right values, or Non in the case of an empty list.

mapCans :: Traversable t => Alternative f => (a -> Can b c) -> t a -> (f b, f c) Source #

Partition a structure by mapping its contents into Cans, and folding over (<|>).

eqCan :: Equivalence (Can a b) Source #

Equivalence relation formed by grouping of equal Can constructors.

# Distributivity

distributeCan :: Can (a, b) c -> (Can a c, Can b c) Source #

Distribute a Can value over a product.

codistributeCan :: Either (Can a c) (Can b c) -> Can (Either a b) c Source #

Codistribute a coproduct over a Can value.

# Associativity

reassocLR :: Can (Can a b) c -> Can a (Can b c) Source #

Re-associate a Can of cans from left to right.

reassocRL :: Can a (Can b c) -> Can (Can a b) c Source #

Re-associate a Can of cans from right to left.

# Symmetry

swapCan :: Can a b -> Can b a Source #

Swap the positions of values in a Can.