{-| Module  : WeakSets
Description : Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory.
Copyright   : Guillaume Sabbagh 2022
License     : GPL-3
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

Pure sets are nested sets which only contain other sets all the way down. They allow to explore basic set theory.

Every mathematical object is a set, usual constructions such as Von Neumann numbers and Kuratowski pairs are implemented.

It is a tree where the order of the branches does not matter.

Functions with the same name as pure set functions are suffixed with the letter 'P' for pure to avoid name collision.
-}

module Math.PureSet 
(
    -- * `PureSet` datatype

    PureSet(..),
    pureSet,
    -- * Mathematical constructions using sets

    emptySet,
    singleton,
    pair,
    cartesianProduct,
    numberToSet,
    (||||),
    (&&&&),
    isInP,
    isIncludedInP,
    card,
    powerSetP,
    -- * Formatting functions

    prettify,
    formatPureSet,
)
where
    import Data.WeakSet (Set)
    import Data.WeakSet.Safe
    import qualified Data.WeakSet as S
    import Data.List    (intersect, nub, intercalate, subsequences)
    import Data.Maybe   (fromJust, catMaybes)
    
    -- | A `PureSet` is a `Set` of other pure sets.

    data PureSet = PureSet (Set PureSet) deriving (PureSet -> PureSet -> Bool
(PureSet -> PureSet -> Bool)
-> (PureSet -> PureSet -> Bool) -> Eq PureSet
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PureSet -> PureSet -> Bool
$c/= :: PureSet -> PureSet -> Bool
== :: PureSet -> PureSet -> Bool
$c== :: PureSet -> PureSet -> Bool
Eq)
    
    instance Show PureSet where
        show :: PureSet -> String
show (PureSet Set PureSet
xs) = String
"(pureSet "String -> ShowS
forall a. [a] -> [a] -> [a]
++ [PureSet] -> String
forall a. Show a => a -> String
show (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) String -> ShowS
forall a. [a] -> [a] -> [a]
++String
")"
    
    -- | Construct a `PureSet` from a list of pure sets.

    pureSet :: [PureSet] -> PureSet
    pureSet :: [PureSet] -> PureSet
pureSet = (Set PureSet -> PureSet
PureSet)(Set PureSet -> PureSet)
-> ([PureSet] -> Set PureSet) -> [PureSet] -> PureSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[PureSet] -> Set PureSet
forall a. [a] -> Set a
set
    
    -- | Peel a `PureSet` into a `Set`.

    pureSetToSet :: PureSet -> Set PureSet
    pureSetToSet :: PureSet -> Set PureSet
pureSetToSet (PureSet Set PureSet
xs) = Set PureSet
xs
    
    -- | Construct the empty set.

    emptySet :: PureSet
    emptySet :: PureSet
emptySet = [PureSet] -> PureSet
pureSet []
  
    -- | Construct the singleton containing a given set.

    singleton :: PureSet -> PureSet
    singleton :: PureSet -> PureSet
singleton PureSet
x = [PureSet] -> PureSet
pureSet ([PureSet] -> PureSet) -> [PureSet] -> PureSet
forall a b. (a -> b) -> a -> b
$ [PureSet
x]
    
    -- | Construct an ordered pair from two sets according to Kuratowski's definition of a tuple.

    pair :: PureSet -> PureSet -> PureSet
    pair :: PureSet -> PureSet -> PureSet
pair PureSet
x PureSet
y = Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set PureSet -> PureSet
forall a b. (a -> b) -> a -> b
$ [PureSet] -> Set PureSet
forall a. [a] -> Set a
set [PureSet -> PureSet
singleton PureSet
x, [PureSet] -> PureSet
pureSet ([PureSet] -> PureSet) -> [PureSet] -> PureSet
forall a b. (a -> b) -> a -> b
$ [PureSet
x,PureSet
y]]
    
    -- | Construct the cartesian product of two sets.

    cartesianProduct :: PureSet -> PureSet -> PureSet
    cartesianProduct :: PureSet -> PureSet -> PureSet
cartesianProduct (PureSet Set PureSet
xs) (PureSet Set PureSet
ys) = [PureSet] -> PureSet
pureSet ([PureSet] -> PureSet) -> [PureSet] -> PureSet
forall a b. (a -> b) -> a -> b
$ [PureSet -> PureSet -> PureSet
pair PureSet
x PureSet
y | PureSet
x <- Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs, PureSet
y <- Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
ys]
    
    -- | Union of two pure sets.

    (||||) :: PureSet -> PureSet -> PureSet
    |||| :: PureSet -> PureSet -> PureSet
(||||) (PureSet Set PureSet
xs) (PureSet Set PureSet
ys) = Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set PureSet -> PureSet
forall a b. (a -> b) -> a -> b
$ Set PureSet
xs Set PureSet -> Set PureSet -> Set PureSet
forall a. Set a -> Set a -> Set a
||| Set PureSet
ys
    
    -- | Intersection of two pure sets.

    (&&&&) :: PureSet -> PureSet -> PureSet
    &&&& :: PureSet -> PureSet -> PureSet
(&&&&) (PureSet Set PureSet
xs) (PureSet Set PureSet
ys) = Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set PureSet -> PureSet
forall a b. (a -> b) -> a -> b
$ Set PureSet
xs Set PureSet -> Set PureSet -> Set PureSet
forall a. Eq a => Set a -> Set a -> Set a
|&| Set PureSet
ys
    
    -- | Difference of two pure sets.

    (\\\\) :: PureSet -> PureSet -> PureSet
    \\\\ :: PureSet -> PureSet -> PureSet
(\\\\) (PureSet Set PureSet
xs) (PureSet Set PureSet
ys) = Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set PureSet -> PureSet
forall a b. (a -> b) -> a -> b
$ Set PureSet
xs Set PureSet -> Set PureSet -> Set PureSet
forall a. Eq a => Set a -> Set a -> Set a
|-| Set PureSet
ys
   
    -- | Transform a number into its Von Neumann construction

    numberToSet :: (Num a, Eq a) => a -> PureSet
    numberToSet :: forall a. (Num a, Eq a) => a -> PureSet
numberToSet a
0 = PureSet
emptySet
    numberToSet a
n = (a -> PureSet
forall a. (Num a, Eq a) => a -> PureSet
numberToSet (a
na -> a -> a
forall a. Num a => a -> a -> a
-a
1)) PureSet -> PureSet -> PureSet
|||| (PureSet -> PureSet
singleton (a -> PureSet
forall a. (Num a, Eq a) => a -> PureSet
numberToSet (a
na -> a -> a
forall a. Num a => a -> a -> a
-a
1)))
    
    -- | Return wether a pure set is in another one.

    isInP :: PureSet -> PureSet -> Bool
    isInP :: PureSet -> PureSet -> Bool
isInP PureSet
x (PureSet Set PureSet
xs) = PureSet
x PureSet -> Set PureSet -> Bool
forall a. Eq a => a -> Set a -> Bool
`isIn` Set PureSet
xs
    
    -- | Return wether a pure set is included in another one.

    isIncludedInP :: PureSet -> PureSet -> Bool
    isIncludedInP :: PureSet -> PureSet -> Bool
isIncludedInP (PureSet Set PureSet
xs) (PureSet Set PureSet
ys) = Set PureSet
xs Set PureSet -> Set PureSet -> Bool
forall a. Eq a => Set a -> Set a -> Bool
`isIncludedIn` Set PureSet
ys
    
    -- | Return the size of a pure set.

    card :: PureSet -> Int
    card :: PureSet -> Int
card (PureSet Set PureSet
xs) = Set PureSet -> Int
forall a. Eq a => Set a -> Int
cardinal Set PureSet
xs
    
    -- | Return the set of subsets of a given set.

    powerSetP :: PureSet -> PureSet
    powerSetP :: PureSet -> PureSet
powerSetP (PureSet Set PureSet
xs) = Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set PureSet -> PureSet
forall a b. (a -> b) -> a -> b
$ Set PureSet -> PureSet
PureSet (Set PureSet -> PureSet) -> Set (Set PureSet) -> Set PureSet
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set PureSet -> Set (Set PureSet)
forall a. Set a -> Set (Set a)
S.powerSet Set PureSet
xs
    
    -- | Prettify a pure set according to usual mathematical notation.

    prettify :: PureSet -> String
    prettify :: PureSet -> String
prettify (PureSet Set PureSet
xs)
        | Set PureSet -> Int
forall a. Eq a => Set a -> Int
cardinal Set PureSet
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = String
"{}"
        | Bool
otherwise = String
"{" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ PureSet -> String
prettify (PureSet -> String) -> [PureSet] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"}"
        
    -- | Format pure sets such that if numbers are recognized, they are transformed into integer and if pairs are recognized, they are transformed into pairs.

    formatPureSet :: PureSet -> String
    formatPureSet :: PureSet -> String
formatPureSet PureSet
x
        | (Bool -> Bool
not(Bool -> Bool) -> (Maybe Integer -> Bool) -> Maybe Integer -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe Integer -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) (Maybe Integer -> Bool) -> Maybe Integer -> Bool
forall a b. (a -> b) -> a -> b
$ PureSet -> Maybe Integer
forall {a}. (Num a, Enum a, Ord a) => PureSet -> Maybe a
toNumber PureSet
x = Integer -> String
forall a. Show a => a -> String
show(Integer -> String)
-> (Maybe Integer -> Integer) -> Maybe Integer -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe Integer -> Integer
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Integer -> String) -> Maybe Integer -> String
forall a b. (a -> b) -> a -> b
$ PureSet -> Maybe Integer
forall {a}. (Num a, Enum a, Ord a) => PureSet -> Maybe a
toNumber PureSet
x
        | (Bool -> Bool
not(Bool -> Bool) -> (Maybe String -> Bool) -> Maybe String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) (Maybe String -> Bool) -> Maybe String -> Bool
forall a b. (a -> b) -> a -> b
$ PureSet -> Maybe String
toPair PureSet
x = Maybe String -> String
forall a. HasCallStack => Maybe a -> a
fromJust(Maybe String -> String)
-> (PureSet -> Maybe String) -> PureSet -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Maybe String
toPair (PureSet -> String) -> PureSet -> String
forall a b. (a -> b) -> a -> b
$ PureSet
x
        | Bool
otherwise = String
"{"String -> ShowS
forall a. [a] -> [a] -> [a]
++String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," (PureSet -> String
formatPureSet (PureSet -> String) -> [PureSet] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList(Set PureSet -> [PureSet])
-> (PureSet -> Set PureSet) -> PureSet -> [PureSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Set PureSet
pureSetToSet (PureSet -> [PureSet]) -> PureSet -> [PureSet]
forall a b. (a -> b) -> a -> b
$ PureSet
x))String -> ShowS
forall a. [a] -> [a] -> [a]
++String
"}"
            where
                toNumber :: PureSet -> Maybe a
toNumber s :: PureSet
s@(PureSet Set PureSet
xs)
                    | PureSet
s PureSet -> PureSet -> Bool
forall a. Eq a => a -> a -> Bool
== PureSet
emptySet = a -> Maybe a
forall a. a -> Maybe a
Just a
0
                    | Bool
otherwise =   let
                                        numbers :: [Maybe a]
numbers = Set (Maybe a) -> [Maybe a]
forall a. Eq a => Set a -> [a]
setToList (Set (Maybe a) -> [Maybe a]) -> Set (Maybe a) -> [Maybe a]
forall a b. (a -> b) -> a -> b
$ PureSet -> Maybe a
toNumber (PureSet -> Maybe a) -> Set PureSet -> Set (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set PureSet
xs
                                        anyMissing :: Bool
anyMissing = Maybe a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Maybe a -> Bool) -> Maybe a -> Bool
forall a b. (a -> b) -> a -> b
$ (Maybe a -> Maybe a -> Maybe a) -> [Maybe a] -> Maybe a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Maybe a -> Maybe a -> Maybe a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>) [Maybe a]
numbers
                                        maxNb :: a
maxNb = [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ [Maybe a] -> [a]
forall a. [Maybe a] -> [a]
catMaybes [Maybe a]
numbers
                                    in 
                                        if (Bool -> Bool
not Bool
anyMissing) Bool -> Bool -> Bool
&& ([Maybe a] -> Set (Maybe a)
forall a. [a] -> Set a
set (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> [a] -> [Maybe a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a
0..a
maxNb])) Set (Maybe a) -> Set (Maybe a) -> Bool
forall a. Eq a => a -> a -> Bool
== ([Maybe a] -> Set (Maybe a)
forall a. [a] -> Set a
set [Maybe a]
numbers) then a -> Maybe a
forall a. a -> Maybe a
Just (a
maxNb a -> a -> a
forall a. Num a => a -> a -> a
+ a
1) else Maybe a
forall a. Maybe a
Nothing
                toPair :: PureSet -> Maybe String
toPair (PureSet Set PureSet
xs)
                    | Set PureSet -> Int
forall a. Eq a => Set a -> Int
cardinal Set PureSet
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 = 
                        case () of
                         () | ((PureSet -> Int
card (PureSet -> Int) -> PureSet -> Int
forall a b. (a -> b) -> a -> b
$ (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& (PureSet -> Int
card (PureSet -> Int) -> PureSet -> Int
forall a b. (a -> b) -> a -> b
$ (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2) Bool -> Bool -> Bool
&& ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0) PureSet -> PureSet -> Bool
`isInP` ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1) -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (PureSet -> String
formatPureSet(PureSet -> String) -> (PureSet -> PureSet) -> PureSet -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[PureSet] -> PureSet
forall a. [a] -> a
head([PureSet] -> PureSet)
-> (PureSet -> [PureSet]) -> PureSet -> PureSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList(Set PureSet -> [PureSet])
-> (PureSet -> Set PureSet) -> PureSet -> [PureSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Set PureSet
pureSetToSet (PureSet -> String) -> PureSet -> String
forall a b. (a -> b) -> a -> b
$ ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0)) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ (PureSet -> String
formatPureSet(PureSet -> String) -> (PureSet -> PureSet) -> PureSet -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[PureSet] -> PureSet
forall a. [a] -> a
head([PureSet] -> PureSet)
-> (PureSet -> [PureSet]) -> PureSet -> PureSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList(Set PureSet -> [PureSet])
-> (PureSet -> Set PureSet) -> PureSet -> [PureSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Set PureSet
pureSetToSet (PureSet -> String) -> PureSet -> String
forall a b. (a -> b) -> a -> b
$ (((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1) PureSet -> PureSet -> PureSet
\\\\ ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0))) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
                            | ((PureSet -> Int
card (PureSet -> Int) -> PureSet -> Int
forall a b. (a -> b) -> a -> b
$ (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& (PureSet -> Int
card (PureSet -> Int) -> PureSet -> Int
forall a b. (a -> b) -> a -> b
$ (Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2) Bool -> Bool -> Bool
&& ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1) PureSet -> PureSet -> Bool
`isInP` ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0) -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (PureSet -> String
formatPureSet(PureSet -> String) -> (PureSet -> PureSet) -> PureSet -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[PureSet] -> PureSet
forall a. [a] -> a
head([PureSet] -> PureSet)
-> (PureSet -> [PureSet]) -> PureSet -> PureSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList(Set PureSet -> [PureSet])
-> (PureSet -> Set PureSet) -> PureSet -> [PureSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Set PureSet
pureSetToSet (PureSet -> String) -> PureSet -> String
forall a b. (a -> b) -> a -> b
$ ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1)) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ (PureSet -> String
formatPureSet(PureSet -> String) -> (PureSet -> PureSet) -> PureSet -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[PureSet] -> PureSet
forall a. [a] -> a
head([PureSet] -> PureSet)
-> (PureSet -> [PureSet]) -> PureSet -> PureSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList(Set PureSet -> [PureSet])
-> (PureSet -> Set PureSet) -> PureSet -> [PureSet]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.PureSet -> Set PureSet
pureSetToSet (PureSet -> String) -> PureSet -> String
forall a b. (a -> b) -> a -> b
$ (((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
0) PureSet -> PureSet -> PureSet
\\\\ ((Set PureSet -> [PureSet]
forall a. Eq a => Set a -> [a]
setToList Set PureSet
xs) [PureSet] -> Int -> PureSet
forall a. [a] -> Int -> a
!! Int
1))) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
                            | Bool
otherwise -> Maybe String
forall a. Maybe a
Nothing
                    | Bool
otherwise = Maybe String
forall a. Maybe a
Nothing