Module

Data.Pointed.Can

Package
purescript-pointed
Repository
vladciobanu/purescript-pointed

This module defines the type Can, along with instances and functions that help use this type. Generally, Can is used when the data is more vague than simply using Either a b or Tuple a b, i.e. when either a or b might be missing or be present independently.

#Can Source

data Can a b

Can a b can hold either no values, an a, a b, or both an a and a b. The type is isomorphic with Maybe (Either (Either a b) (Tuple a b)).

Constructors

Instances

#fromRepr Source

fromRepr :: forall b a. Maybe (Either (Either a b) (Tuple a b)) -> Can a b

Constructs a Can given an isomorphic representation. Note that this is the precise inverse of toRepr.

> fromRepr Nothing :: Can String Int
Non

> fromRepr (Just (Left (Left "hello"))) :: Can String Int
One "hello"

> fromRepr (Just (Left (Right 42))) :: Can String Int
Eno 42

> fromRepr (Just (Right (Tuple "hello" 42))) :: Can String Int
Two "hello" 42

#toRepr Source

toRepr :: forall b a. Can a b -> Maybe (Either (Either a b) (Tuple a b))

Destructs a Can to its isomorphic representation. Note that this is the precise inverse of fromRepr.

> toRepr (Non :: Can String Int)
Nothing

> toRepr (One "hello" :: Can String Int)
Just (Left (Left "hello"))

> toRepr (Eno 42 :: Can String Int)
Just (Left (Right 42))

> toRepr Two "hello" 42
Just (Right (Tuple "hello" 42))

#fromMaybe Source

fromMaybe :: forall b a. Maybe a -> Maybe b -> Can a b

Construct a Can from a pair of Maybes.

> fromMaybe Nothing Nothing :: Can String Int
Non

> fromMaybe (Just "hello") Nothing :: Can String Int
One "hello"

> fromMaybe Nothing (Just 42) :: Can String Int
Eno 42

> fromMaybe (Just "hello") (Just 42) :: Can String Int
Two "hello" 42

#can Source

can :: forall c b a. c -> (a -> c) -> (b -> c) -> (a -> b -> c) -> Can a b -> c

Can catamorphism (fold). Takes an input for each possible constructor and translates it to c.

For example, we can go from some c :: Can a b to a Maybe (Either (Either a b) (Tuple a b)) using:

> can Nothing (Left <<< Left) (Left <<< Right) (\a b -> Right (Tuple a b)) (Non :: Can String Int)
Nothing

> can Nothing (Left <<< Left) (Left <<< Right) (\a b -> Right (Tuple a b)) (One "hello" :: Can String Int)
Just (Left (Left "hello"))

> can Nothing (Left <<< Left) (Left <<< Right) (\a b -> Right (Tuple a b)) (Eno 42 :: Can String Int)
Just (Left (Right 42))

> can Nothing (Left <<< Left) (Left <<< Right) (\a b -> Right (Tuple a b)) (Two "hello" 42 :: Can String Int)
Just (Right (Tuple "hello" 42))

#first Source

first :: forall b a. Can a b -> Maybe a

Grabs an a if it exists, otherwise returns nothing. Note that this function grabs an a from either the One or the Two constructors.

> first (Non :: Can String Int)
Nothing

> first (One "hello" :: Can String Int)
Just "hello"

> first (Eno 42 :: Can String Int)
Nothing

> first (Two "hello" 42)
Just "hello"

#second Source

second :: forall b a. Can a b -> Maybe b

Grabs a b if it exists, otherwise returns nothing. Note that this function grabs a b from either the Eno or the Two constructors.

> second (Non :: Can String Int)
Nothing

> second (One "hello" :: Can String Int)
Nothing

> second (Eno 42 :: Can String Int)
Just 42

> second (Two "hello" 42)
Just 42

#both Source

both :: forall b a. Can a b -> Maybe (Tuple a b)

Grabs both an a and a b if they both exist, from the Two constructor.

> both (Non :: Can String Int)
Nothing

> both (One "hello" :: Can String Int)
Nothing

> both (Eno 42 :: Can String Int)
Nothing

> both (Two "hello" 42)
Just (Tuple "hello" 42)

#isNone Source

isNone :: forall b a. Can a b -> Boolean

Checks if the constructor is Non.

> isNone (Non :: Can String Int)
true

> isNone (One "hello" :: Can String Int)
false

> isNone (Eno 42 :: Can String Int)
false

> isNone (Two "hello" 42)
false

#isOne Source

isOne :: forall b a. Can a b -> Boolean

Checks if the constructor is One.

> isOne (Non :: Can String Int)
false

> isOne (One "hello" :: Can String Int)
true

> isOne (Eno 42 :: Can String Int)
false

> isOne (Two "hello" 42)
false

#isEno Source

isEno :: forall b a. Can a b -> Boolean

Checks if the constructor is Eno.

> isEno (Non :: Can String Int)
false

> isEno (One "hello" :: Can String Int)
false

> isEno (Eno 42 :: Can String Int)
true

> isEno (Two "hello" 42)
false

#isTwo Source

isTwo :: forall b a. Can a b -> Boolean

Checks if the constructor is Two.

> isTwo (Non :: Can String Int)
false

> isTwo (One "hello" :: Can String Int)
false

> isTwo (Eno 42 :: Can String Int)
false

> isTwo (Two "hello" 42)
true

#ones Source

ones :: forall f b a. Functor f => Foldable f => f (Can a b) -> List a

Takes all a values from a Foldable Can. Note that values are extracted from both the One and Two constructors.

> ones [Non :: Can String Int]
Nil

> ones ([One "hello", One "world"] :: Array (Can String Int))
Cons "hello" (Cons "world" Nil)

> ones ([Eno 42, Eno 13] :: Array (Can String Int))
Nil

> ones ([Two "hello" 42, Two "world" 1] :: Array (Can String Int))
Cons "hello" (Cons "world" Nil)

> ones [One "hello", Eno 42, Two "world" 13]
Cons "hello" (Cons "world" Nil)

#enos Source

enos :: forall f b a. Functor f => Foldable f => f (Can a b) -> List b

Takes all b values from a Foldable Can. Note that values are extracted from both the Eno and Two constructors.

> enos [Non :: Can String Int]
Nil

> enos ([One "hello", One "world"] :: Array (Can String Int))
Nil

> enos ([Eno 42, Eno 13] :: Array (Can String Int))
Cons 42 (Cons 13 Nil)

> enos ([Two "hello" 42, Two "world" 13] :: Array (Can String Int))
Cons 42 (Cons 13 Nil)

> enos [One "hello", Eno 42, Two "world" 13]
Cons 42 (Cons 13 Nil)

#twos Source

twos :: forall f b a. Functor f => Foldable f => f (Can a b) -> List (Tuple a b)

Takes all a and b values from a Foldable Can. Note that values are only extracted from the Two constructor.

> twos [Non :: Can String Int]
Nil

> twos ([One "hello", One "world"] :: Array (Can String Int))
Nil

> twos ([Eno "hello", Eno "world"] :: Array (Can String Int))
Nil

> twos ([Two "hello" 42, Two "world" 1] :: Array (Can String Int))
Cons (Tuple "hello" 42) (Cons (Tuple "world" 1) Nil)

#curry Source

curry :: forall c b a. (Can a b -> Maybe c) -> Maybe a -> Maybe b -> Maybe c

Expand a Can a b to a Maybe a and a Maybe b. Note that the tuple Tuple (Maybe a) (Maybe b) is exactly equivalent with Can a b:

- Nothing, Nothing ~ Non
- Just a , Nothing ~ One a
- Nothing, Just b  ~ Eno b
- Just a , Just b  ~ Two a b

#uncurry Source

uncurry :: forall c b a. (Maybe a -> Maybe b -> Maybe c) -> Can a b -> Maybe c

Contract a Maybe a and a Maybe b to a Can a b. Note that Can a b is exactly equivalent with Tuple (Maybe a) (Maybe b):

Non     ~ Nothing, Nothing
One a   ~ Just a , Nothing
Eno b   ~ Nothing, Just b
Two a b ~ Just a , Just b

#partition Source

partition :: forall b a t f. Foldable t => Alternative f => t (Can a b) -> Tuple (f a) (f b)

Grab all a and b values from a Foldable Can a b and combine them each into an Alternative f tuple.

> partition [Non, One "hello", Eno 42, Two "world" 1] :: Tuple (List String) (List Int)
Tuple (Cons "hello" (Cons "world" Nil)) (Cons 42 (Cons 1 Nil))

#partitionMap Source

partitionMap :: forall c b a t f. Alternative f => Traversable t => (a -> Can b c) -> t a -> Tuple (f b) (f c)

Maps Cans over a Traversable and partitions the values by their position in the Can.

> partitionMap (\i -> if i < 3 then One i else Eno i) [1, 2, 3, 4, 5] :: Tuple (Array Int) (Array Int)
Tuple [1, 2] [3, 4, 5]

#distribute Source

distribute :: forall c b a. Can (Tuple a b) c -> Tuple (Can a c) (Can b c)

Distribute Can over a Tuple.

> distribute (Non :: Can (Tuple String String) Int)
Tuple Non Non

> distribute (One (Tuple "hello" "world") :: Can (Tuple String String) Int)
Tuple (One "hello") (One "world")

> distribute (Eno 42 :: Can (Tuple String String) Int)
Tuple (Eno 42) (Eno 42)

> distribute (Two (Tuple "hello" "world") 42 :: Can (Tuple String String) Int)
Tuple (Two "hello" 42) (Two "world" 42)

#codistribute Source

codistribute :: forall c b a. Either (Can a c) (Can b c) -> Can (Either a b) c

Codistribute Either over a Can.

> codistribute (Left Non :: Either (Can String Int) (Can Boolean Int))
Non

> codistribute (Left (One "hello") :: Either (Can String Int) (Can Boolean Int))
One (Left "hello")

> codistribute (Left (Eno 42) :: Either (Can String Int) (Can Boolean Int))
Eno 42

> codistribute (Left (Two "hello" 42) :: Either (Can String Int) (Can Boolean Int))
Two (Left "hello") 42

> codistribute (Right Non :: Either (Can String Int) (Can Boolean Int))
Non

> codistribute (Right (One true) :: Either (Can String Int) (Can Boolean Int))
One (Right true)

> codistribute (Right (Eno 42) :: Either (Can String Int) (Can Boolean Int))
Eno 42

> codistribute (Right (Two true 42) :: Either (Can String Int) (Can Boolean Int))
Two (Right true) 42

#reassocLR Source

reassocLR :: forall c b a. Can (Can a b) c -> Can a (Can b c)

Reassociates a Can from left to right. Note that Eno c and Two Non c both collapse to Eno (Eno c), so it is NOT the case that reassocLR <<< reassocRL = identity.

#reassocRL Source

reassocRL :: forall c b a. Can a (Can b c) -> Can (Can a b) c

Reassociates a Can from right to left. Note that Eno c and Two Non c both collapse to Eno (Eno c), so it is NOT the case that reassocLR <<< reassocRL = identity.

#swap Source

swap :: forall b a. Can a b -> Can b a

Swap the inputs for a Can.

> swap (Non :: Can String Int)
Non

> swap (One "hello" :: Can String Int)
Eno "hello"

> swap (Eno 42 :: Can String Int)
One 42

> swap (Two "hello" 42)
Two 42 "hello"