smash-0.1.1.0: Combinators for Maybe types

Copyright (c) 2020 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 (Either (Either a b) (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

# 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

# Folding

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.

# 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 :: forall f t a b. (Foldable t, Alternative f) => 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 :: forall f t a b c. (Alternative f, Traversable t) => (a -> Can b c) -> t a -> (f b, f c) Source #

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

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