exotic-list-monads-1.1.1: Non-standard monads on lists and non-empty lists
Copyright(c) Dylan McDermott Maciej Piróg Tarmo Uustalu 2020
LicenseMIT
Maintainermaciej.adam.pirog@gmail.com
Stabilityexperimental
Portabilityportable
Safe HaskellTrustworthy
LanguageHaskell2010

Control.Monad.List.Exotic

Description

The usual list monad is only one of infinitely many ways to turn the List functor into a monad. This module collects a number of such non-standard "list" monads.

Notes:

  • Types marked with "(?)" have not been formally verified to be monads (yet), though they were thoroughly tested with billions of QuickCheck tests.
  • Monads in this module are defined in terms of join rather than >>=. The return of every monad is singleton (it is not known if there exists a monad on lists with a different return).
  • For readability, code snippets in this documentation assume the OverloadedLists and OverloadedStrings language extensions, which make it possible to omit some newtype constructors. Example definitions of joins of monads always skip the newtype constructors, that is, assume >>= is always defined as follows for a particular local join:
m >>= f = wrap $ join $ map (unwrap . f) $ unwrap m
 where
  join = ...
  • The definitions of monads are optimized for readability and not run-time performance. This is because the monads in this module don't seem to be of any practical use, they are more of a theoretical curiosity.

References:

Most of the monads defined in this module have been introduced in the following papers (although there are some new specimens as well):

Synopsis

List monads in general

class Monad m => ListMonad m where Source #

In this module, a "list monad" is a monad in which the underlying functor is isomorphic to List. We require:

wrap . unwrap  ==  id
unwrap . wrap  ==  id

There is a default implementation provided if m is known to be a list (meaning m a is an instance of IsList for all a).

Minimal complete definition

Nothing

Methods

wrap :: [a] -> m a Source #

default wrap :: (IsList (m a), Item (m a) ~ a) => [a] -> m a Source #

unwrap :: m a -> [a] Source #

default unwrap :: (IsList (m a), Item (m a) ~ a) => m a -> [a] Source #

Instances

Instances details
ListMonad DiscreteHybrid Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> DiscreteHybrid a Source #

unwrap :: DiscreteHybrid a -> [a] Source #

ListMonad GlobalFailure Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> GlobalFailure a Source #

unwrap :: GlobalFailure a -> [a] Source #

ListMonad ListUnfold Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ListUnfold a Source #

unwrap :: ListUnfold a -> [a] Source #

ListMonad MazeWalk Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> MazeWalk a Source #

unwrap :: MazeWalk a -> [a] Source #

ListMonad Mini Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Mini a Source #

unwrap :: Mini a -> [a] Source #

ListMonad Odd Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Odd a Source #

unwrap :: Odd a -> [a] Source #

ListMonad [] Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> [a] Source #

unwrap :: [a] -> [a] Source #

KnownNat n => ListMonad (AtLeast n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> AtLeast n a Source #

unwrap :: AtLeast n a -> [a] Source #

KnownNat n => ListMonad (AtMost n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> AtMost n a Source #

unwrap :: AtMost n a -> [a] Source #

SetOfNats s => ListMonad (ContinuumOfMonads s) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ContinuumOfMonads s a Source #

unwrap :: ContinuumOfMonads s a -> [a] Source #

NumericalMonoidGenerators ns => ListMonad (NumericalMonoidMonad ns) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> NumericalMonoidMonad ns a Source #

unwrap :: NumericalMonoidMonad ns a -> [a] Source #

KnownNat n => ListMonad (Stutter n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Stutter n a Source #

unwrap :: Stutter n a -> [a] Source #

KnownNat n => ListMonad (StutterKeeper n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> StutterKeeper n a Source #

unwrap :: StutterKeeper n a -> [a] Source #

ListMonad m => ListMonad (DualListMonad m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> DualListMonad m a Source #

unwrap :: DualListMonad m a -> [a] Source #

(KnownNat n, KnownNat p) => ListMonad (ShortStutterKeeper n p) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ShortStutterKeeper n p a Source #

unwrap :: ShortStutterKeeper n p a -> [a] Source #

(KnownNat n, KnownNat m) => ListMonad (StutterStutter n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> StutterStutter n m a Source #

unwrap :: StutterStutter n m a -> [a] Source #

newtype DualListMonad m a Source #

Every list monad has a dual, in which join is defined as

reverse . join . reverse . fmap reverse

(where join is the join of the original list monad).

return is the same as in the original monad.

Constructors

DualListMonad 

Fields

Instances

Instances details
ListMonad m => Applicative (DualListMonad m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> DualListMonad m a #

(<*>) :: DualListMonad m (a -> b) -> DualListMonad m a -> DualListMonad m b #

liftA2 :: (a -> b -> c) -> DualListMonad m a -> DualListMonad m b -> DualListMonad m c #

(*>) :: DualListMonad m a -> DualListMonad m b -> DualListMonad m b #

(<*) :: DualListMonad m a -> DualListMonad m b -> DualListMonad m a #

Functor m => Functor (DualListMonad m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> DualListMonad m a -> DualListMonad m b #

(<$) :: a -> DualListMonad m b -> DualListMonad m a #

ListMonad m => Monad (DualListMonad m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: DualListMonad m a -> (a -> DualListMonad m b) -> DualListMonad m b #

(>>) :: DualListMonad m a -> DualListMonad m b -> DualListMonad m b #

return :: a -> DualListMonad m a #

ListMonad m => ListMonad (DualListMonad m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> DualListMonad m a Source #

unwrap :: DualListMonad m a -> [a] Source #

(ListMonad m, IsList (m a)) => IsList (DualListMonad m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (DualListMonad m a) #

Show (m a) => Show (DualListMonad m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq (m a) => Eq (DualListMonad m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: DualListMonad m a -> DualListMonad m a -> Bool #

(/=) :: DualListMonad m a -> DualListMonad m a -> Bool #

type Item (DualListMonad m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (DualListMonad m a) = Item (m a)

isSingle :: [a] -> Bool Source #

Checks if a given list is a singleton (= list of length one).

Monads with finite presentation

This section contains monads that come about from free algebras of theories with a finite number of operations, represented as type classes. Coincidentally, all theories in this module have one binary and one nullary operation, that is, each is a subclass of PointedMagma with additional laws. (So does the usual list monad, where the subclass is monoid.) It is not known if there exists a list monad that has a finite presentation but necessarily with a different set of operations (there are such monads on non-empty lists, for example, HeadTails and HeadsTail).

Pointed magmas

class PointedMagma a where Source #

Pointed magmas are structures with one binary operation and one constant. In general, no laws are imposed.

Methods

eps :: a Source #

(<>) :: a -> a -> a Source #

Instances

Instances details
PointedMagma (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma [a] Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

eps :: [a] Source #

(<>) :: [a] -> [a] -> [a] Source #

KnownNat n => PointedMagma (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

eps :: Stutter n a Source #

(<>) :: Stutter n a -> Stutter n a -> Stutter n a Source #

KnownNat n => PointedMagma (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat m) => PointedMagma (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

class ListMonad m => FreeRBPM m (c :: Type -> Constraint) | m -> c where Source #

A class for free right-braketed (subclasses of) pointed magmas.

All monads defined in this section arise from subclasses of PointedMagma, in which we do not assume any additional methods, but require the instances to satisfy additional equations. This means that the monad is not only an instance of such a class that defines a type of algebra, but it is free such algebra.

In particular, we consider theories c in which the equations have the following shapes:

x <> eps       ==  ...
eps <> x       ==  ...
(x <> y) <> z  ==  ...

Moreover, when read left-to-right, they form a terminating and confluent rewriting system with normal forms of the following shape:

eps
x <> (y <> ( ... (z <> t) ... ))

This class offers a witness that a particular list monad m is a free algebra of the theory c. This gives us the function

foldRBPM _ (unwrap -> []) = eps
foldRBPM f (unwrap -> xs) = foldr1 (<>) (map f xs)

which is the unique lifting of an interpretation of generators to a homomorphism (between algebras of this sort) from the list monad to any algebra (an instance) of c.

Note that the default definition of foldRBPM is always the right one for right-bracketed subclasses of PointedMagma, so it is enough to declare the relationship, for example:

instance FreeRBPM [] Monoid

Minimal complete definition

Nothing

Methods

foldRBPM :: (PointedMagma a, c a) => (x -> a) -> m x -> a Source #

Instances

Instances details
FreeRBPM DiscreteHybrid LeaningAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, LeaningAlgebra a) => (x -> a) -> DiscreteHybrid x -> a Source #

FreeRBPM GlobalFailure ZeroSemigroup Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, ZeroSemigroup a) => (x -> a) -> GlobalFailure x -> a Source #

FreeRBPM ListUnfold SkewedAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, SkewedAlgebra a) => (x -> a) -> ListUnfold x -> a Source #

FreeRBPM MazeWalk PalindromeAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, PalindromeAlgebra a) => (x -> a) -> MazeWalk x -> a Source #

FreeRBPM [] Monoid Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, Monoid a) => (x -> a) -> [x] -> a Source #

KnownNat n => FreeRBPM (Stutter n) (StutterAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterAlgebra n a) => (x -> a) -> Stutter n x -> a Source #

KnownNat n => FreeRBPM (StutterKeeper n) (StutterKeeperAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterKeeperAlgebra n a) => (x -> a) -> StutterKeeper n x -> a Source #

(KnownNat n, KnownNat m) => FreeRBPM (StutterStutter n m) (StutterStutterAlgebra n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterStutterAlgebra n m a) => (x -> a) -> StutterStutter n m x -> a Source #

The Global Failure monad

class PointedMagma a => ZeroSemigroup a Source #

A zero semigroup has an associative binary operation and a constant that is absorbing on both sides. That is, the following equations hold:

x <> eps       ==  eps
eps <> x       ==  eps
(x <> y) <> z  ==  x <> (y <> z)

Instances

Instances details
FreeRBPM GlobalFailure ZeroSemigroup Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, ZeroSemigroup a) => (x -> a) -> GlobalFailure x -> a Source #

ZeroSemigroup (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

newtype GlobalFailure a Source #

The Global Failure monad arises from free zero semigroups. It implements a kind of nondeterminism similar to the usual List monad, but failing (= resulting in the empty list) in one branch makes the entire computation fail. Its join is defined as:

join xss | any null xss = []
         | otherwise    = concat xss

For example:

>>> [1, 2, 3] >>= (\n -> [1..n]) :: GlobalFailure Int
GlobalFailure [1,1,2,1,2,3]
>>> [1, 0, 3] >>= (\n -> [1..n]) :: GlobalFailure Int
GlobalFailure []

Constructors

GlobalFailure 

Fields

Instances

Instances details
Applicative GlobalFailure Source # 
Instance details

Defined in Control.Monad.List.Exotic

Functor GlobalFailure Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> GlobalFailure a -> GlobalFailure b #

(<$) :: a -> GlobalFailure b -> GlobalFailure a #

Monad GlobalFailure Source # 
Instance details

Defined in Control.Monad.List.Exotic

ListMonad GlobalFailure Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> GlobalFailure a Source #

unwrap :: GlobalFailure a -> [a] Source #

FreeRBPM GlobalFailure ZeroSemigroup Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, ZeroSemigroup a) => (x -> a) -> GlobalFailure x -> a Source #

IsString (GlobalFailure Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (GlobalFailure a) #

Show a => Show (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

ZeroSemigroup (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (GlobalFailure a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (GlobalFailure a) = a

The Maze Walk monad

class PointedMagma a => PalindromeAlgebra a Source #

A palindrome algebra is a pointed magma that satisfies the following equations:

x <> eps       ==  eps
eps <> x       ==  eps
(x <> y) <> z  ==  x <> (y <> (x <> z))

Instances

Instances details
FreeRBPM MazeWalk PalindromeAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, PalindromeAlgebra a) => (x -> a) -> MazeWalk x -> a Source #

PalindromeAlgebra (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

palindromize :: [a] -> [a] Source #

Turns a list into a palindrome by appending it and its reversed init. For example:

palindromize []       ==  []
palindromize "Ringo"  ==  "RingogniR"

newtype MazeWalk a Source #

The Maze Walk monad arises from free palindrome algebras. Its join is defined as:

join xss | null xss     = []
         | any null xss = []
         | otherwise    = concatMap palindromize (init xss) ++ last xss

Intuitively, it is a list of values one encounters when walking a path in a maze. The bind operation attaches to each value a new "corridor" to visit. In our walk we explore every such corridor. For example, consider the following expression:

>>> join ["John", "Paul", "George", "Ringo"] :: MazeWalk Char
MazeWalk "JohnhoJPauluaPGeorgegroeGRingo"

It represents a walk through the following maze (the entrance is marked with ">"):

  ┌────┬──────┐
  │L U │ N G O│
  ├─┤A ┴ I┌───┘
 > J P G R│
┌─┘O ┬ E ┌┘
│N H │ O └──┐
└────┤ R G E│
     └──────┘

First, we take the J-O-H-N path. When we reach its end, we turn around and go back to J, so our walk to this point is J-O-H-N-H-O-J (hence the connection with palindromes). Then, we explore the P-A-U-L corridor, adding P-A-U-L-U-A-P to our walk. The same applies to G-E-O-R-G-E. But when at the end of R-I-N-G-O, we have explored the entire maze, so our walk is done (this is why we do not palindromize the last element).

Constructors

MazeWalk 

Fields

Instances

Instances details
Applicative MazeWalk Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> MazeWalk a #

(<*>) :: MazeWalk (a -> b) -> MazeWalk a -> MazeWalk b #

liftA2 :: (a -> b -> c) -> MazeWalk a -> MazeWalk b -> MazeWalk c #

(*>) :: MazeWalk a -> MazeWalk b -> MazeWalk b #

(<*) :: MazeWalk a -> MazeWalk b -> MazeWalk a #

Functor MazeWalk Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> MazeWalk a -> MazeWalk b #

(<$) :: a -> MazeWalk b -> MazeWalk a #

Monad MazeWalk Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: MazeWalk a -> (a -> MazeWalk b) -> MazeWalk b #

(>>) :: MazeWalk a -> MazeWalk b -> MazeWalk b #

return :: a -> MazeWalk a #

ListMonad MazeWalk Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> MazeWalk a Source #

unwrap :: MazeWalk a -> [a] Source #

FreeRBPM MazeWalk PalindromeAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, PalindromeAlgebra a) => (x -> a) -> MazeWalk x -> a Source #

IsString (MazeWalk Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (MazeWalk a) #

Methods

fromList :: [Item (MazeWalk a)] -> MazeWalk a #

fromListN :: Int -> [Item (MazeWalk a)] -> MazeWalk a #

toList :: MazeWalk a -> [Item (MazeWalk a)] #

Show a => Show (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> MazeWalk a -> ShowS #

show :: MazeWalk a -> String #

showList :: [MazeWalk a] -> ShowS #

PalindromeAlgebra (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: MazeWalk a -> MazeWalk a -> Bool #

(/=) :: MazeWalk a -> MazeWalk a -> Bool #

type Item (MazeWalk a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (MazeWalk a) = a

The Discrete Hybrid monad

class PointedMagma a => LeaningAlgebra a Source #

Instances should satisfy the following:

x <> eps       ==  eps
eps <> x       ==  x
(x <> y) <> z  ==  y <> z

Instances

Instances details
FreeRBPM DiscreteHybrid LeaningAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, LeaningAlgebra a) => (x -> a) -> DiscreteHybrid x -> a Source #

LeaningAlgebra (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

safeLast :: [a] -> [a] Source #

A singleton list with the last element of the argument, if it exists. Otherwise, empty.

safeLast "Roy"  ==  "y"
safeLast []     ==  []

newtype DiscreteHybrid a Source #

The Discrete Hybrid monad arises from free leaning algebras. Its join is defined as:

join xss | null xss        = []
         | null (last xss) = []
         | otherwise       = concatMap safeLast (init xss) ++ last xss

For example:

>>> join ["Roy", "Kelton", "Orbison"] :: DiscreteHybrid Char
DiscreteHybrid "ynOrbison"
>>> join ["Roy", "", "Orbison"] :: DiscreteHybrid Char
DiscreteHybrid "yOrbison"

Constructors

DiscreteHybrid 

Fields

Instances

Instances details
Applicative DiscreteHybrid Source # 
Instance details

Defined in Control.Monad.List.Exotic

Functor DiscreteHybrid Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> DiscreteHybrid a -> DiscreteHybrid b #

(<$) :: a -> DiscreteHybrid b -> DiscreteHybrid a #

Monad DiscreteHybrid Source # 
Instance details

Defined in Control.Monad.List.Exotic

ListMonad DiscreteHybrid Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> DiscreteHybrid a Source #

unwrap :: DiscreteHybrid a -> [a] Source #

FreeRBPM DiscreteHybrid LeaningAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, LeaningAlgebra a) => (x -> a) -> DiscreteHybrid x -> a Source #

IsString (DiscreteHybrid Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (DiscreteHybrid a) #

Show a => Show (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

LeaningAlgebra (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (DiscreteHybrid a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (DiscreteHybrid a) = a

The List Unfold monad

class PointedMagma a => SkewedAlgebra a Source #

A skewed algebra allows only right-nested composition of the binary operation. Every other expression is equal to eps.

x <> eps       ==  eps
eps <> x       ==  eps
(x <> y) <> z  ==  eps

Instances

Instances details
FreeRBPM ListUnfold SkewedAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, SkewedAlgebra a) => (x -> a) -> ListUnfold x -> a Source #

SkewedAlgebra (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

newtype ListUnfold a Source #

The List Unfold monad arises from free skewed algebras. It implements a form of nondeterminism similar to the usual list monad, but new choices may arise only in the last element (so the bind operation can only rename other elements), essentially unfolding a list. If new choices arise in the "init" of the list, the entire computation fails. Also, failure is always global. The join operation is defined as follows:

join xss | null xss                        = []
         | any null xss                    = []
         | any (not . isSingle) (init xss) = []
         | otherwise                       = concat xss

For example:

>>> [1,1,1,4] >>= \x -> [1..x] :: ListUnfold Int
ListUnfold [1,1,1,1,2,3,4]
>>> [1,2,1,4] >>= \x -> [1..x] :: ListUnfold Int
ListUnfold []
>>> [1,0,1,4] >>= \x -> [1..x] :: ListUnfold Int
ListUnfold []

Constructors

ListUnfold 

Fields

Instances

Instances details
Applicative ListUnfold Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> ListUnfold a #

(<*>) :: ListUnfold (a -> b) -> ListUnfold a -> ListUnfold b #

liftA2 :: (a -> b -> c) -> ListUnfold a -> ListUnfold b -> ListUnfold c #

(*>) :: ListUnfold a -> ListUnfold b -> ListUnfold b #

(<*) :: ListUnfold a -> ListUnfold b -> ListUnfold a #

Functor ListUnfold Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> ListUnfold a -> ListUnfold b #

(<$) :: a -> ListUnfold b -> ListUnfold a #

Monad ListUnfold Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: ListUnfold a -> (a -> ListUnfold b) -> ListUnfold b #

(>>) :: ListUnfold a -> ListUnfold b -> ListUnfold b #

return :: a -> ListUnfold a #

ListMonad ListUnfold Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ListUnfold a Source #

unwrap :: ListUnfold a -> [a] Source #

FreeRBPM ListUnfold SkewedAlgebra Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, SkewedAlgebra a) => (x -> a) -> ListUnfold x -> a Source #

IsString (ListUnfold Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (ListUnfold a) #

Show a => Show (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

PointedMagma (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

SkewedAlgebra (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: ListUnfold a -> ListUnfold a -> Bool #

(/=) :: ListUnfold a -> ListUnfold a -> Bool #

type Item (ListUnfold a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (ListUnfold a) = a

The Stutter monad

class (KnownNat n, PointedMagma a) => StutterAlgebra n a Source #

A stutter algebra (for a given natural number n) is a pointed magma that satisfies the following equations:

x <> eps       ==  foldr1 (<>) (replicate (n + 2) x)
eps <> x       ==  eps  
(x <> y) <> z  ==  eps

Instances

Instances details
KnownNat n => StutterAlgebra n (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => FreeRBPM (Stutter n) (StutterAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterAlgebra n a) => (x -> a) -> Stutter n x -> a Source #

replicateLast :: Int -> [a] -> [a] Source #

Repeat the last element on the list n additional times, that is:

replicateLast n [] = []
replicateLast n xs = xs ++ replicate n (last xs)

newtype Stutter (n :: Nat) a Source #

The Stutter monad arises from free stutter algebras. Its join is a concat of the longest prefix consisting only of singletons with a "stutter" on the last singleton (that is, the last singleton is additionally repeated n+1 times for an n fixed in the type). It doesn't stutter only when the init consists only of singletons and the last list is non-empty. The join can thus be defined as follows (omitting the conversion of the type-level Nat n to a run-time value):

join xss | null xss
         = []
         | any (not . isSingle) (init xss) || null (last xss)
         = replicateLast (n + 1) (concat $ takeWhile isSingle (init xss))
         | otherwise
         = concat xss

The Stutter monad is quite similar to ListUnfold. The difference is that when the latter fails (that is, its join results in the empty list), the former stutters on the last singleton.

Examples:

>>> join ["1", "2", "buckle", "my", "shoe"] :: Stutter 5 Char
Stutter "12222222"
>>> join ["1", "2", "buckle"] :: Stutter 5 Char
Stutter "12buckle"
>>> join ["1", "2", "", "my", "shoe"] :: Stutter 5 Char
Stutter "12222222"

Constructors

Stutter 

Fields

Instances

Instances details
KnownNat n => StutterAlgebra n (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => Applicative (Stutter n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> Stutter n a #

(<*>) :: Stutter n (a -> b) -> Stutter n a -> Stutter n b #

liftA2 :: (a -> b -> c) -> Stutter n a -> Stutter n b -> Stutter n c #

(*>) :: Stutter n a -> Stutter n b -> Stutter n b #

(<*) :: Stutter n a -> Stutter n b -> Stutter n a #

Functor (Stutter n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> Stutter n a -> Stutter n b #

(<$) :: a -> Stutter n b -> Stutter n a #

KnownNat n => Monad (Stutter n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: Stutter n a -> (a -> Stutter n b) -> Stutter n b #

(>>) :: Stutter n a -> Stutter n b -> Stutter n b #

return :: a -> Stutter n a #

KnownNat n => ListMonad (Stutter n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Stutter n a Source #

unwrap :: Stutter n a -> [a] Source #

KnownNat n => FreeRBPM (Stutter n) (StutterAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterAlgebra n a) => (x -> a) -> Stutter n x -> a Source #

KnownNat n => IsString (Stutter n Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fromString :: String -> Stutter n Char #

KnownNat n => IsList (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (Stutter n a) #

Methods

fromList :: [Item (Stutter n a)] -> Stutter n a #

fromListN :: Int -> [Item (Stutter n a)] -> Stutter n a #

toList :: Stutter n a -> [Item (Stutter n a)] #

Show a => Show (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> Stutter n a -> ShowS #

show :: Stutter n a -> String #

showList :: [Stutter n a] -> ShowS #

KnownNat n => PointedMagma (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

eps :: Stutter n a Source #

(<>) :: Stutter n a -> Stutter n a -> Stutter n a Source #

Eq a => Eq (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: Stutter n a -> Stutter n a -> Bool #

(/=) :: Stutter n a -> Stutter n a -> Bool #

type Item (Stutter n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (Stutter n a) = a

The Stutter-Keeper monad

class (KnownNat n, PointedMagma a) => StutterKeeperAlgebra n a Source #

A stutter-keeper algebra (for a given natural number n) is a pointed magma that satisfies the following equations:

x <> eps       ==  foldr1 (<>) (replicate (n + 2) x)
eps <> x       ==  eps  
(x <> y) <> z  ==  x <> y

Instances

Instances details
KnownNat n => StutterKeeperAlgebra n (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => FreeRBPM (StutterKeeper n) (StutterKeeperAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterKeeperAlgebra n a) => (x -> a) -> StutterKeeper n x -> a Source #

newtype StutterKeeper (n :: Nat) a Source #

The stutter-keeper monad arises from free stutter-keeper algebras. Its join stutters (as in the Stutter monad) if the first non-singleton list is empty. Otherwise, it keeps the singleton prefix, and keeps the first non-singleton list. The join can thus be defined as follows (omitting the conversion of the type-level Nat n to a run-time value):

join xss | null xss
         = []
         | null (head (dropWhile isSingle (init xss) ++ [last xss]))
         = replicateLast (n + 1) (concat $ takeWhile isSingle (init xss))
         | otherwise
         = map head (takeWhile isSingle (init xss))
            ++ head (dropWhile isSingle (init xss) ++ [last xss])

Examples:

>>> join ["1", "2", "buckle", "my", "shoe"] :: StutterKeeper 5 Char
StutterKeeper "12buckle"
>>> join ["1", "2", "buckle"] :: StutterKeeper 5 Char
StutterKeeper "12buckle"
>>> join ["1", "2", "", "my", "shoe"] :: StutterKeeper 5 Char
StutterKeeper "12222222"

Constructors

StutterKeeper 

Fields

Instances

Instances details
KnownNat n => StutterKeeperAlgebra n (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => Applicative (StutterKeeper n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> StutterKeeper n a #

(<*>) :: StutterKeeper n (a -> b) -> StutterKeeper n a -> StutterKeeper n b #

liftA2 :: (a -> b -> c) -> StutterKeeper n a -> StutterKeeper n b -> StutterKeeper n c #

(*>) :: StutterKeeper n a -> StutterKeeper n b -> StutterKeeper n b #

(<*) :: StutterKeeper n a -> StutterKeeper n b -> StutterKeeper n a #

Functor (StutterKeeper n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> StutterKeeper n a -> StutterKeeper n b #

(<$) :: a -> StutterKeeper n b -> StutterKeeper n a #

KnownNat n => Monad (StutterKeeper n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: StutterKeeper n a -> (a -> StutterKeeper n b) -> StutterKeeper n b #

(>>) :: StutterKeeper n a -> StutterKeeper n b -> StutterKeeper n b #

return :: a -> StutterKeeper n a #

KnownNat n => ListMonad (StutterKeeper n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> StutterKeeper n a Source #

unwrap :: StutterKeeper n a -> [a] Source #

KnownNat n => FreeRBPM (StutterKeeper n) (StutterKeeperAlgebra n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterKeeperAlgebra n a) => (x -> a) -> StutterKeeper n x -> a Source #

KnownNat n => IsString (StutterKeeper n Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => IsList (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (StutterKeeper n a) #

Show a => Show (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

KnownNat n => PointedMagma (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: StutterKeeper n a -> StutterKeeper n a -> Bool #

(/=) :: StutterKeeper n a -> StutterKeeper n a -> Bool #

type Item (StutterKeeper n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (StutterKeeper n a) = a

The Stutter-Stutter monad

class (KnownNat n, KnownNat m, PointedMagma a) => StutterStutterAlgebra n m a Source #

A stutter-stutter algebra (for given natural numbers n and m) is a pointed magma that satisfies the following equations:

x <> eps       ==  foldr1 (<>) (replicate (n + 2) x)
eps <> x       ==  eps  
(x <> y) <> z  ==  foldr1 (<>) (replicate (m + 2) x)

Instances

Instances details
(KnownNat n, KnownNat m) => StutterStutterAlgebra n m (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat m) => FreeRBPM (StutterStutter n m) (StutterStutterAlgebra n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterStutterAlgebra n m a) => (x -> a) -> StutterStutter n m x -> a Source #

newtype StutterStutter (n :: Nat) (m :: Nat) a Source #

The stutter-stutter monad arises from free stutter-stutter algebras. It is similar to StutterKeeper, but instead of keeping the first non-singleton list, it stutters on its first element (unless the first non-singleton list is also the last list, in which case it is kept in the result). The join can thus be defined as follows (omitting the conversion of the type-level nats to run-time values):

join xss | null xss
         = []
         | null (head (dropWhile isSingle (init xss) ++ [last xss]))
         = replicateLast (n + 1) (concat $ takeWhile isSingle (init xss))
         | any (not . isSingle) (init xss) || null (last xss)
         = concat (takeWhile isSingle (init xss))
            ++ replicate (m + 2) (head (head (dropWhile isSingle (init xss))))
         | otherwise
         = concat xss

Examples:

>>> join ["1", "2", "buckle", "my", "shoe"] :: StutterStutter 5 10 Char
StutterStutter "12bbbbbbbbbbbb"
>>> join ["1", "2", "buckle"] :: StutterStutter 5 10 Char
StutterStutter "12buckle"
>>> join ["1", "2", "", "my", "shoe"] :: StutterStutter 5 10 Char
StutterStutter "12222222"

Constructors

StutterStutter 

Fields

Instances

Instances details
(KnownNat n, KnownNat m) => StutterStutterAlgebra n m (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat m) => Applicative (StutterStutter n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> StutterStutter n m a #

(<*>) :: StutterStutter n m (a -> b) -> StutterStutter n m a -> StutterStutter n m b #

liftA2 :: (a -> b -> c) -> StutterStutter n m a -> StutterStutter n m b -> StutterStutter n m c #

(*>) :: StutterStutter n m a -> StutterStutter n m b -> StutterStutter n m b #

(<*) :: StutterStutter n m a -> StutterStutter n m b -> StutterStutter n m a #

Functor (StutterStutter n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> StutterStutter n m a -> StutterStutter n m b #

(<$) :: a -> StutterStutter n m b -> StutterStutter n m a #

(KnownNat n, KnownNat m) => Monad (StutterStutter n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: StutterStutter n m a -> (a -> StutterStutter n m b) -> StutterStutter n m b #

(>>) :: StutterStutter n m a -> StutterStutter n m b -> StutterStutter n m b #

return :: a -> StutterStutter n m a #

(KnownNat n, KnownNat m) => ListMonad (StutterStutter n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> StutterStutter n m a Source #

unwrap :: StutterStutter n m a -> [a] Source #

(KnownNat n, KnownNat m) => FreeRBPM (StutterStutter n m) (StutterStutterAlgebra n m) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

foldRBPM :: (PointedMagma a, StutterStutterAlgebra n m a) => (x -> a) -> StutterStutter n m x -> a Source #

(KnownNat n, KnownNat m) => IsString (StutterStutter n m Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat m) => IsList (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (StutterStutter n m a) #

Methods

fromList :: [Item (StutterStutter n m a)] -> StutterStutter n m a #

fromListN :: Int -> [Item (StutterStutter n m a)] -> StutterStutter n m a #

toList :: StutterStutter n m a -> [Item (StutterStutter n m a)] #

Show a => Show (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> StutterStutter n m a -> ShowS #

show :: StutterStutter n m a -> String #

showList :: [StutterStutter n m a] -> ShowS #

(KnownNat n, KnownNat m) => PointedMagma (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: StutterStutter n m a -> StutterStutter n m a -> Bool #

(/=) :: StutterStutter n m a -> StutterStutter n m a -> Bool #

type Item (StutterStutter n m a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (StutterStutter n m a) = a

Monads from numerical monoids

A numerical monoid is a subset of the set of natural numbers that contains 0 and is closed under addition. That is, \(M \subseteq \mathbb N\) is a numerical monoid if

  • \(0 \in M\),
  • if \(x,y \in M\), then \(x+y \in M\).

Representing a numerical monoid \(M\) using its characteristic function m :: Int -> Bool (revealing if a given number belongs to \(M\)), we can define a monad as follows:

join xss | isSingle xss || all isSingle xss                         = concat xss
         | null xss || any null xss                                 = []
         | m (length xss - 1) && all (\xs -> m $ length xs - 1) xss = concat xss
         | otherwise                                                = []

There is also some intuition behind the "- 1" part: For a set \(M \subseteq \mathbb N\), we define a set shifted by 1 as \(M^{+} =\{x \in \mathbb N \ |\ x-1 \in M\}\). Then, \(M\) is a numerical monoid if and only if:

  • \(1 \in M^{+}\),
  • if \(n, x_1, \ldots, x_n \in M^{+}\), then \(\displaystyle \sum_{i = 0}^n x_i \in M^{+}\).

(Do note that in the above \(n\) is in \(M^{+}\) as well!) This means that \(M^{+}\) is a set of "accepted lengths" of lists, while the condition above states that when we concatenate an accepted number of accepted lists, we still obtain an accepted list. This in turn can be used to prove the associativity law for monads: breadly speaking, join :: [[[a]]] -> [a] is a concat only if all the lists on all levels are of accepted lengths (save for the unit laws), and joining (either the inner lists or the outer list first) will not produce a non-accepted list.

Below, we first show a couple of concrete examples of monads arising from particular numerical monoids, and then the general version via a set of generators, NumericalMonoidMonad.

The Mini monad

newtype Mini a Source #

The Mini monad is, in a sense, a minimal list monad, meaning that its join fails (= results in the empty list) for all values except the ones that appear in the unit laws (i.e., a singleton or a list of singletons):

join xss | isSingle xss || all isSingle xss = concat xss
         | otherwise                        = []

For example:

>>> join ["HelloThere"] :: Mini Char
Mini "HelloThere"
>>> join ["Hello", "There"] :: Mini Char
Mini ""
>>> join ["H", "T"] :: Mini Char
Mini "HT"

This monad arises from the numerical monoid \(\{0\}\).

It does not arise from a subclass of PointedMagma (or any algebraic theory with a finite number of operations for that matter).

Constructors

Mini 

Fields

Instances

Instances details
Applicative Mini Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> Mini a #

(<*>) :: Mini (a -> b) -> Mini a -> Mini b #

liftA2 :: (a -> b -> c) -> Mini a -> Mini b -> Mini c #

(*>) :: Mini a -> Mini b -> Mini b #

(<*) :: Mini a -> Mini b -> Mini a #

Functor Mini Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> Mini a -> Mini b #

(<$) :: a -> Mini b -> Mini a #

Monad Mini Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: Mini a -> (a -> Mini b) -> Mini b #

(>>) :: Mini a -> Mini b -> Mini b #

return :: a -> Mini a #

ListMonad Mini Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Mini a Source #

unwrap :: Mini a -> [a] Source #

IsString (Mini Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fromString :: String -> Mini Char #

IsList (Mini a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (Mini a) #

Methods

fromList :: [Item (Mini a)] -> Mini a #

fromListN :: Int -> [Item (Mini a)] -> Mini a #

toList :: Mini a -> [Item (Mini a)] #

Show a => Show (Mini a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> Mini a -> ShowS #

show :: Mini a -> String #

showList :: [Mini a] -> ShowS #

Eq a => Eq (Mini a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: Mini a -> Mini a -> Bool #

(/=) :: Mini a -> Mini a -> Bool #

type Item (Mini a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (Mini a) = a

The Odd monad

newtype Odd a Source #

The join of the Odd monad is a concat of the inner lists provided there is an odd number of them, and that all of them are of odd length themselves. Otherwise (modulo cases needed for the unit laws), the result is the empty list.

join xss | isSingle xss || all isSingle xss  = concat xss
         | odd (length xss)
            && all (odd . length) xss        = concat xss 
         | otherwise                         = []

For example:

>>> join ["Elvis", "Presley"] :: Odd Char
Odd ""
>>> join ["Elvis", "Aaron", "Presley"] :: Odd Char
Odd "ElvisAaronPresley"
>>> join ["Roy", "Kelton", "Orbison"] :: Odd Char
Odd ""

It arises from the numerical monoid \(\{0,2,4,6,\ldots\}\). -- Note that the sum of even numbers is always even, which cannot be said of odd numbers!

At the moment, it is unclear whether it comes from a finite algebraic theory.

Constructors

Odd 

Fields

Instances

Instances details
Applicative Odd Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> Odd a #

(<*>) :: Odd (a -> b) -> Odd a -> Odd b #

liftA2 :: (a -> b -> c) -> Odd a -> Odd b -> Odd c #

(*>) :: Odd a -> Odd b -> Odd b #

(<*) :: Odd a -> Odd b -> Odd a #

Functor Odd Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> Odd a -> Odd b #

(<$) :: a -> Odd b -> Odd a #

Monad Odd Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: Odd a -> (a -> Odd b) -> Odd b #

(>>) :: Odd a -> Odd b -> Odd b #

return :: a -> Odd a #

ListMonad Odd Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> Odd a Source #

unwrap :: Odd a -> [a] Source #

IsString (Odd Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fromString :: String -> Odd Char #

IsList (Odd a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (Odd a) #

Methods

fromList :: [Item (Odd a)] -> Odd a #

fromListN :: Int -> [Item (Odd a)] -> Odd a #

toList :: Odd a -> [Item (Odd a)] #

Show a => Show (Odd a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> Odd a -> ShowS #

show :: Odd a -> String #

showList :: [Odd a] -> ShowS #

Eq a => Eq (Odd a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: Odd a -> Odd a -> Bool #

(/=) :: Odd a -> Odd a -> Bool #

type Item (Odd a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (Odd a) = a

The At Least monad

newtype AtLeast (n :: Nat) a Source #

The join of the AtLeast n monad is a concat of the inner lists provided there are at least n inner lists and all the inner lists are of length at least n or 1 (plus the cases required by the unit laws).

The join can thus be defined as follows (omitting the conversion of the type-level nats to run-time values):

join xss | isSingle xss || all isSingle xss  = concat xss
         | otherwise = let ok :: forall x. [x] -> Bool
                           ok xs = length xs >= n || length xs == 1
                       in if ok xss && all ok xss
                            then concat xss
                            else []

For example:

>>> join ["Strawberry", "Fields", "Forever"] :: AtLeast 3 Char
AtLeast "StrawberryFieldsForever"
>>> join ["All", "You", "Need", "Is", "Love"] :: AtLeast 3 Char
AtLeast []
>>> join ["I", "Want", "You"] :: AtLeast 3 Char
AtLeast "IWantYou"
>>> join ["I", "Am", "The", "Walrus"] :: AtLeast 3 Char
AtLeast []

The monad AtLeast n arises from the numerical monoid \(\{0, n-1, n, n+1, n+2,\ldots\}\).

Constructors

AtLeast 

Fields

Instances

Instances details
KnownNat n => Applicative (AtLeast n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> AtLeast n a #

(<*>) :: AtLeast n (a -> b) -> AtLeast n a -> AtLeast n b #

liftA2 :: (a -> b -> c) -> AtLeast n a -> AtLeast n b -> AtLeast n c #

(*>) :: AtLeast n a -> AtLeast n b -> AtLeast n b #

(<*) :: AtLeast n a -> AtLeast n b -> AtLeast n a #

Functor (AtLeast n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> AtLeast n a -> AtLeast n b #

(<$) :: a -> AtLeast n b -> AtLeast n a #

KnownNat n => Monad (AtLeast n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: AtLeast n a -> (a -> AtLeast n b) -> AtLeast n b #

(>>) :: AtLeast n a -> AtLeast n b -> AtLeast n b #

return :: a -> AtLeast n a #

KnownNat n => ListMonad (AtLeast n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> AtLeast n a Source #

unwrap :: AtLeast n a -> [a] Source #

KnownNat n => IsString (AtLeast n Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fromString :: String -> AtLeast n Char #

KnownNat n => IsList (AtLeast n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (AtLeast n a) #

Methods

fromList :: [Item (AtLeast n a)] -> AtLeast n a #

fromListN :: Int -> [Item (AtLeast n a)] -> AtLeast n a #

toList :: AtLeast n a -> [Item (AtLeast n a)] #

Show a => Show (AtLeast n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> AtLeast n a -> ShowS #

show :: AtLeast n a -> String #

showList :: [AtLeast n a] -> ShowS #

Eq a => Eq (AtLeast n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: AtLeast n a -> AtLeast n a -> Bool #

(/=) :: AtLeast n a -> AtLeast n a -> Bool #

type Item (AtLeast n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (AtLeast n a) = a

The Numerical Monoid monad

class NumericalMonoidGenerators (ns :: [Nat]) where Source #

An interesting property of numerical monoids is that they are always finitely generated. This means that every numerical monoid can be constructed by starting out with a finite set of nautral numbers and closing it under addition. For example, the set \(\{0,2,4,6,\ldots\}\) is generated by \(\{2\}\), because every even number is of the form \(2k\) for some \(k\).

The class NumericalMonoidGenerators represents a set of generators given as a type-level list of nats.

Methods

isInNumericalMonoid :: Int -> Bool Source #

Check if a given number is in the numerical monoid generatted by ns. It is the characteristic function of the generated numerical monoid.

Instances

Instances details
NumericalMonoidGenerators ('[] :: [Nat]) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat g, NumericalMonoidGenerators gs) => NumericalMonoidGenerators (g ': gs) Source # 
Instance details

Defined in Control.Monad.List.Exotic

newtype NumericalMonoidMonad (ns :: [Nat]) a Source #

The monad generated by the numerical monoid generated by a set of generators ns.

join xss | null xss || any null xss                                     = []
         | isInNumericalMonoid @ns (length xss - 1)
            && all (\xs -> isInNumericalMonoid @ns (length xs - 1)) xss = concat xss
         | otherwise                                                    = []

In particular:

  • Mini is equivalent to NumericalMonoidMonad '[],
  • GlobalFailure is equivalent to NumericalMonoidMonad '[1],
  • Odd is equivalent to NumericalMonoidMonad '[2],
  • AtLeast n is equivalent to NumericalMonoidMonad '[n-1, n, n+1, ..., 2n-3].

Constructors

NumericalMonoidMonad 

Fields

Instances

Instances details
NumericalMonoidGenerators ns => Applicative (NumericalMonoidMonad ns) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Functor (NumericalMonoidMonad ns) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> NumericalMonoidMonad ns a -> NumericalMonoidMonad ns b #

(<$) :: a -> NumericalMonoidMonad ns b -> NumericalMonoidMonad ns a #

NumericalMonoidGenerators ns => Monad (NumericalMonoidMonad ns) Source # 
Instance details

Defined in Control.Monad.List.Exotic

NumericalMonoidGenerators ns => ListMonad (NumericalMonoidMonad ns) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> NumericalMonoidMonad ns a Source #

unwrap :: NumericalMonoidMonad ns a -> [a] Source #

IsString (NumericalMonoidMonad ns Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (NumericalMonoidMonad ns a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (NumericalMonoidMonad ns a) #

Show a => Show (NumericalMonoidMonad ns a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (NumericalMonoidMonad ns a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (NumericalMonoidMonad ns a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (NumericalMonoidMonad ns a) = a

Other list monads

The At Most monad

newtype AtMost (n :: Nat) a Source #

The monad whose join is concat, but only if the total length of the list (that is, the sum of the lengths of the inner lists) is not greater than n (except for the unit laws and the "global failure" property):

join xss | isSingle xss || all isSingle xss = concat xss
         | any null xss                     = []
         | length (concat xss) <= n         = concat xss
         | otherwise                        = []

For example:

>>> join ["El","vis"] :: AtMost 5 Char
AtMost "Elvis"
>>> join ["El","v","i"] :: AtMost 5 Char
AtMost "Elvi"
>>> join ["El","","vis"] :: AtMost 5 Char
AtMost ""
>>> join ["Presley"] :: AtMost 5 Char
AtMost "Presley"
>>> join ["P","r","e","s","l","e","y"] :: AtMost 5 Char
AtMost "Presley"
>>> join ["Pre","s","ley"] :: AtMost 5 Char
AtMost ""

Constructors

AtMost 

Fields

Instances

Instances details
KnownNat n => Applicative (AtMost n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

pure :: a -> AtMost n a #

(<*>) :: AtMost n (a -> b) -> AtMost n a -> AtMost n b #

liftA2 :: (a -> b -> c) -> AtMost n a -> AtMost n b -> AtMost n c #

(*>) :: AtMost n a -> AtMost n b -> AtMost n b #

(<*) :: AtMost n a -> AtMost n b -> AtMost n a #

Functor (AtMost n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> AtMost n a -> AtMost n b #

(<$) :: a -> AtMost n b -> AtMost n a #

KnownNat n => Monad (AtMost n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(>>=) :: AtMost n a -> (a -> AtMost n b) -> AtMost n b #

(>>) :: AtMost n a -> AtMost n b -> AtMost n b #

return :: a -> AtMost n a #

KnownNat n => ListMonad (AtMost n) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> AtMost n a Source #

unwrap :: AtMost n a -> [a] Source #

KnownNat n => IsString (AtMost n Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fromString :: String -> AtMost n Char #

KnownNat n => IsList (AtMost n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (AtMost n a) #

Methods

fromList :: [Item (AtMost n a)] -> AtMost n a #

fromListN :: Int -> [Item (AtMost n a)] -> AtMost n a #

toList :: AtMost n a -> [Item (AtMost n a)] #

Show a => Show (AtMost n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

showsPrec :: Int -> AtMost n a -> ShowS #

show :: AtMost n a -> String #

showList :: [AtMost n a] -> ShowS #

Eq a => Eq (AtMost n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

(==) :: AtMost n a -> AtMost n a -> Bool #

(/=) :: AtMost n a -> AtMost n a -> Bool #

type Item (AtMost n a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (AtMost n a) = a

The Continuum-of-Monads monad

The "Continuum of Monads" monad construction was introduced in this paper to show that the set of list monads is a continuum (that is, that there are as many list monads in the category of sets as there are real numbers, and more than there are natural numbers).

We define a family of monads ContinuumOfMonads, which is parameterised by a subset of the set of natural numbers (SetOfNats).

class SetOfNats (a :: Symbol) where Source #

The SetOfNats class defines a subset of the set of natural numbers (from which we are actually interested in odd numbers only). We give two instances, Primes and Fib, as examples, so if one wants to construct their own monad, they need to define an instance first: any total elemOf gives a monad.

For example:

>>> filter (elemOf @"Primes") [0..100]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
>>> filter (elemOf @"Fib") [0..100]
[0,1,2,3,5,8,13,21,34,55,89]

Methods

elemOf :: Int -> Bool Source #

The characteristic function of the defined set.

Instances

Instances details
SetOfNats "Fib" Source #

The set of Fibonacci numbers.

Instance details

Defined in Control.Monad.List.Exotic

Methods

elemOf :: Int -> Bool Source #

SetOfNats "Primes" Source #

The set of prime numbers.

Instance details

Defined in Control.Monad.List.Exotic

Methods

elemOf :: Int -> Bool Source #

newtype ContinuumOfMonads (s :: Symbol) a Source #

The ContinuumOfMonads monad is parameterised by a set of natural numbers (a symbol that instantiates SetOfNats).

The join of ContinuumOfMonads s is defined as follows:

join xss       | isSingle xss    || all isSingle xss      = concat xss
               | null xss        || any null xss          = []
join [[x], xs] | odd (length xs) && elemOf @s (length xs) = x : xs
join _                                                    = []

For example:

>>> join [[0],[1,2,3]] :: ContinuumOfMonads "Primes" Int
ContinuumOfMonads [0,1,2,3]
>>> join [[0],[1,2,3,4]] :: ContinuumOfMonads "Primes" Int
ContinuumOfMonads []
>>> join [[0,1],[1,2,3,4,5]] :: ContinuumOfMonads "Primes" Int
ContinuumOfMonads []

Constructors

ContinuumOfMonads 

Fields

Instances

Instances details
SetOfNats s => Applicative (ContinuumOfMonads s) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Functor (ContinuumOfMonads s) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> ContinuumOfMonads s a -> ContinuumOfMonads s b #

(<$) :: a -> ContinuumOfMonads s b -> ContinuumOfMonads s a #

SetOfNats s => Monad (ContinuumOfMonads s) Source # 
Instance details

Defined in Control.Monad.List.Exotic

SetOfNats s => ListMonad (ContinuumOfMonads s) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ContinuumOfMonads s a Source #

unwrap :: ContinuumOfMonads s a -> [a] Source #

IsString (ContinuumOfMonads s Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

IsList (ContinuumOfMonads s a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (ContinuumOfMonads s a) #

Show a => Show (ContinuumOfMonads s a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (ContinuumOfMonads s a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (ContinuumOfMonads s a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (ContinuumOfMonads s a) = a

The Short Stutter-Keeper monad (?)

newtype ShortStutterKeeper (n :: Nat) (p :: Nat) a Source #

This monad works just like the StutterKeeper monad but it takes a prefix of the result of join of length p+2 (unless the unit laws say otherwise). Thus, its join is defined as follows (omitting the conversion of the type-level Nat p to a run-time value):

join xss | isSingle xss     = concat xss
         | all isSingle xss = concat xss
         | otherwise        = take (p + 2) $ toList
                                ((Control.Monad.join $ StutterKeeper $ fmap StutterKeeper xss)
                                  :: StutterKeeper n _)

For example:

>>> join ["1", "2", "buckle", "my", "shoe"] :: ShortStutterKeeper 5 2 Char
ShortStutterKeeper "12bu"
>>> join ["1", "2", "buckle"] :: ShortStutterKeeper 5 2 Char
ShortStutterKeeper "12bu"
>>> join ["1", "2", "", "my", "shoe"] :: ShortStutterKeeper 5 2 Char
ShortStutterKeeper "1222"

Compare the ShortFront monad on non-empty lists.

Constructors

ShortStutterKeeper 

Fields

Instances

Instances details
(KnownNat n, KnownNat p) => Applicative (ShortStutterKeeper n p) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Functor (ShortStutterKeeper n p) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

fmap :: (a -> b) -> ShortStutterKeeper n p a -> ShortStutterKeeper n p b #

(<$) :: a -> ShortStutterKeeper n p b -> ShortStutterKeeper n p a #

(KnownNat n, KnownNat p) => Monad (ShortStutterKeeper n p) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat p) => ListMonad (ShortStutterKeeper n p) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Methods

wrap :: [a] -> ShortStutterKeeper n p a Source #

unwrap :: ShortStutterKeeper n p a -> [a] Source #

(KnownNat n, KnownNat p) => IsString (ShortStutterKeeper n p Char) Source # 
Instance details

Defined in Control.Monad.List.Exotic

(KnownNat n, KnownNat p) => IsList (ShortStutterKeeper n p a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Associated Types

type Item (ShortStutterKeeper n p a) #

Show a => Show (ShortStutterKeeper n p a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

Eq a => Eq (ShortStutterKeeper n p a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (ShortStutterKeeper n p a) Source # 
Instance details

Defined in Control.Monad.List.Exotic

type Item (ShortStutterKeeper n p a) = a