{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, Safe #-}

{-|
Module      : Data.Char.Brackets
Description : Determine and manipulate bracket characters.
Maintainer  : hapytexeu+gh@gmail.com
Stability   : experimental
Portability : POSIX

Unicode considers 60 characters to be brackets: brackets are organized in /pairs/: each opening bracket has a corresponding closing bracket and vice versa.

The following characters are considered brackets where the first character is closed by the last character, the second by the last but one, etc.:

@
([{༺༼᚛⁅⁽₍⌈⌊〈❨❪❬❮❰❲❴⟅⟦⟨⟪⟬⟮⦃⦅⦇⦉⦋⦍⦏⦑⦓⦕⦗⧘⧚⧼⸢⸤⸦⸨〈《「『【〔〖〘〚﹙﹛﹝([{⦅「」⦆}])﹞﹜﹚〛〙〗〕】』」》〉⸩⸧⸥⸣⧽⧛⧙⦘⦖⦔⦒⦎⦐⦌⦊⦈⦆⦄⟯⟭⟫⟩⟧⟆❵❳❱❯❭❫❩〉⌋⌉₎⁾⁆᚜༽༻}])
@

These characters span over several code blocks.
-}


module Data.Char.Brackets (
  -- * Listing and converting brackets
    bracketMaps, brackets, openBrackets, closeBrackets, toOpen, toClose
  -- * Check the given bracket type
  , BracketType(Open, Close), isBracket, bracketType, bracketType', isOpenBracket, isCloseBracket
  -- * Determine the opposite bracket
  , getOppositeChar, getOppositeChar'
  ) where

import Prelude hiding (lookup)

import Control.Applicative((<|>))
import Control.DeepSeq(NFData)

import Data.Data(Data)
import Data.Hashable(Hashable)
import Data.Map(Map, fromList, lookup, member)
import Data.Maybe(fromMaybe)
import Data.Tuple(swap)

import GHC.Generics(Generic)

import Test.QuickCheck.Arbitrary(Arbitrary(arbitrary), arbitraryBoundedEnum)

-- | A data type that is used to specify the /type/ of bracket.
data BracketType
  = Open  -- ^ The bracket is used to "open" a context.
  | Close  -- ^ The bracket is used to "close" a context.
  deriving (BracketType
BracketType -> BracketType -> Bounded BracketType
forall a. a -> a -> Bounded a
maxBound :: BracketType
$cmaxBound :: BracketType
minBound :: BracketType
$cminBound :: BracketType
Bounded, Typeable BracketType
DataType
Constr
Typeable BracketType
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BracketType -> c BracketType)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c BracketType)
-> (BracketType -> Constr)
-> (BracketType -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c BracketType))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c BracketType))
-> ((forall b. Data b => b -> b) -> BracketType -> BracketType)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BracketType -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BracketType -> r)
-> (forall u. (forall d. Data d => d -> u) -> BracketType -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> BracketType -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> BracketType -> m BracketType)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BracketType -> m BracketType)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BracketType -> m BracketType)
-> Data BracketType
BracketType -> DataType
BracketType -> Constr
(forall b. Data b => b -> b) -> BracketType -> BracketType
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BracketType -> c BracketType
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BracketType
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BracketType -> u
forall u. (forall d. Data d => d -> u) -> BracketType -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BracketType -> m BracketType
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BracketType -> m BracketType
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BracketType
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BracketType -> c BracketType
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BracketType)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BracketType)
$cClose :: Constr
$cOpen :: Constr
$tBracketType :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> BracketType -> m BracketType
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BracketType -> m BracketType
gmapMp :: (forall d. Data d => d -> m d) -> BracketType -> m BracketType
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BracketType -> m BracketType
gmapM :: (forall d. Data d => d -> m d) -> BracketType -> m BracketType
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BracketType -> m BracketType
gmapQi :: Int -> (forall d. Data d => d -> u) -> BracketType -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BracketType -> u
gmapQ :: (forall d. Data d => d -> u) -> BracketType -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> BracketType -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BracketType -> r
gmapT :: (forall b. Data b => b -> b) -> BracketType -> BracketType
$cgmapT :: (forall b. Data b => b -> b) -> BracketType -> BracketType
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BracketType)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BracketType)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c BracketType)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BracketType)
dataTypeOf :: BracketType -> DataType
$cdataTypeOf :: BracketType -> DataType
toConstr :: BracketType -> Constr
$ctoConstr :: BracketType -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BracketType
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BracketType
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BracketType -> c BracketType
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BracketType -> c BracketType
$cp1Data :: Typeable BracketType
Data, Int -> BracketType
BracketType -> Int
BracketType -> [BracketType]
BracketType -> BracketType
BracketType -> BracketType -> [BracketType]
BracketType -> BracketType -> BracketType -> [BracketType]
(BracketType -> BracketType)
-> (BracketType -> BracketType)
-> (Int -> BracketType)
-> (BracketType -> Int)
-> (BracketType -> [BracketType])
-> (BracketType -> BracketType -> [BracketType])
-> (BracketType -> BracketType -> [BracketType])
-> (BracketType -> BracketType -> BracketType -> [BracketType])
-> Enum BracketType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: BracketType -> BracketType -> BracketType -> [BracketType]
$cenumFromThenTo :: BracketType -> BracketType -> BracketType -> [BracketType]
enumFromTo :: BracketType -> BracketType -> [BracketType]
$cenumFromTo :: BracketType -> BracketType -> [BracketType]
enumFromThen :: BracketType -> BracketType -> [BracketType]
$cenumFromThen :: BracketType -> BracketType -> [BracketType]
enumFrom :: BracketType -> [BracketType]
$cenumFrom :: BracketType -> [BracketType]
fromEnum :: BracketType -> Int
$cfromEnum :: BracketType -> Int
toEnum :: Int -> BracketType
$ctoEnum :: Int -> BracketType
pred :: BracketType -> BracketType
$cpred :: BracketType -> BracketType
succ :: BracketType -> BracketType
$csucc :: BracketType -> BracketType
Enum, BracketType -> BracketType -> Bool
(BracketType -> BracketType -> Bool)
-> (BracketType -> BracketType -> Bool) -> Eq BracketType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BracketType -> BracketType -> Bool
$c/= :: BracketType -> BracketType -> Bool
== :: BracketType -> BracketType -> Bool
$c== :: BracketType -> BracketType -> Bool
Eq, (forall x. BracketType -> Rep BracketType x)
-> (forall x. Rep BracketType x -> BracketType)
-> Generic BracketType
forall x. Rep BracketType x -> BracketType
forall x. BracketType -> Rep BracketType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BracketType x -> BracketType
$cfrom :: forall x. BracketType -> Rep BracketType x
Generic, Eq BracketType
Eq BracketType
-> (BracketType -> BracketType -> Ordering)
-> (BracketType -> BracketType -> Bool)
-> (BracketType -> BracketType -> Bool)
-> (BracketType -> BracketType -> Bool)
-> (BracketType -> BracketType -> Bool)
-> (BracketType -> BracketType -> BracketType)
-> (BracketType -> BracketType -> BracketType)
-> Ord BracketType
BracketType -> BracketType -> Bool
BracketType -> BracketType -> Ordering
BracketType -> BracketType -> BracketType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BracketType -> BracketType -> BracketType
$cmin :: BracketType -> BracketType -> BracketType
max :: BracketType -> BracketType -> BracketType
$cmax :: BracketType -> BracketType -> BracketType
>= :: BracketType -> BracketType -> Bool
$c>= :: BracketType -> BracketType -> Bool
> :: BracketType -> BracketType -> Bool
$c> :: BracketType -> BracketType -> Bool
<= :: BracketType -> BracketType -> Bool
$c<= :: BracketType -> BracketType -> Bool
< :: BracketType -> BracketType -> Bool
$c< :: BracketType -> BracketType -> Bool
compare :: BracketType -> BracketType -> Ordering
$ccompare :: BracketType -> BracketType -> Ordering
$cp1Ord :: Eq BracketType
Ord, ReadPrec [BracketType]
ReadPrec BracketType
Int -> ReadS BracketType
ReadS [BracketType]
(Int -> ReadS BracketType)
-> ReadS [BracketType]
-> ReadPrec BracketType
-> ReadPrec [BracketType]
-> Read BracketType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BracketType]
$creadListPrec :: ReadPrec [BracketType]
readPrec :: ReadPrec BracketType
$creadPrec :: ReadPrec BracketType
readList :: ReadS [BracketType]
$creadList :: ReadS [BracketType]
readsPrec :: Int -> ReadS BracketType
$creadsPrec :: Int -> ReadS BracketType
Read, Int -> BracketType -> ShowS
[BracketType] -> ShowS
BracketType -> String
(Int -> BracketType -> ShowS)
-> (BracketType -> String)
-> ([BracketType] -> ShowS)
-> Show BracketType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BracketType] -> ShowS
$cshowList :: [BracketType] -> ShowS
show :: BracketType -> String
$cshow :: BracketType -> String
showsPrec :: Int -> BracketType -> ShowS
$cshowsPrec :: Int -> BracketType -> ShowS
Show)

instance Arbitrary BracketType where
  arbitrary :: Gen BracketType
arbitrary = Gen BracketType
forall a. (Bounded a, Enum a) => Gen a
arbitraryBoundedEnum

instance Hashable BracketType

instance NFData BracketType

-- | A list of 2-tuples where the first item
-- of each tuple is the opening bracket, and the
-- second item its closing counterpart.
bracketMaps :: [(Char, Char)]
bracketMaps :: [(Char, Char)]
bracketMaps = [
    (Char
'(', Char
')')
  , (Char
'[', Char
']')
  , (Char
'{', Char
'}')
  , (Char
'\x0f3a', Char
'\x0f3b')
  , (Char
'\x0f3c', Char
'\x0f3d')
  , (Char
'\x169b', Char
'\x169c')
  , (Char
'\x2045', Char
'\x2046')
  , (Char
'\x207d', Char
'\x207e')
  , (Char
'\x208d', Char
'\x208e')
  , (Char
'\x2308', Char
'\x2309')
  , (Char
'\x230a', Char
'\x230b')
  , (Char
'\x2329', Char
'\x232a')
  , (Char
'\x2768', Char
'\x2769')
  , (Char
'\x276a', Char
'\x276b')
  , (Char
'\x276c', Char
'\x276d')
  , (Char
'\x276e', Char
'\x276f')
  , (Char
'\x2770', Char
'\x2771')
  , (Char
'\x2772', Char
'\x2773')
  , (Char
'\x2774', Char
'\x2775')
  , (Char
'\x27c5', Char
'\x27c6')
  , (Char
'\x27e6', Char
'\x27e7')
  , (Char
'\x27e8', Char
'\x27e9')
  , (Char
'\x27ea', Char
'\x27eb')
  , (Char
'\x27ec', Char
'\x27ed')
  , (Char
'\x27ee', Char
'\x27ef')
  , (Char
'\x2983', Char
'\x2984')
  , (Char
'\x2985', Char
'\x2986')
  , (Char
'\x2987', Char
'\x2988')
  , (Char
'\x2989', Char
'\x298a')
  , (Char
'\x298b', Char
'\x298c')
  , (Char
'\x298d', Char
'\x2990')
  , (Char
'\x298f', Char
'\x298e')
  , (Char
'\x2991', Char
'\x2992')
  , (Char
'\x2993', Char
'\x2994')
  , (Char
'\x2995', Char
'\x2996')
  , (Char
'\x2997', Char
'\x2998')
  , (Char
'\x29d8', Char
'\x29d9')
  , (Char
'\x29da', Char
'\x29db')
  , (Char
'\x29fc', Char
'\x29fd')
  , (Char
'\x2e22', Char
'\x2e23')
  , (Char
'\x2e24', Char
'\x2e25')
  , (Char
'\x2e26', Char
'\x2e27')
  , (Char
'\x2e28', Char
'\x2e29')
  , (Char
'\x3008', Char
'\x3009')
  , (Char
'\x300a', Char
'\x300b')
  , (Char
'\x300c', Char
'\x300d')
  , (Char
'\x300e', Char
'\x300f')
  , (Char
'\x3010', Char
'\x3011')
  , (Char
'\x3014', Char
'\x3015')
  , (Char
'\x3016', Char
'\x3017')
  , (Char
'\x3018', Char
'\x3019')
  , (Char
'\x301a', Char
'\x301b')
  , (Char
'\xfe59', Char
'\xfe5a')
  , (Char
'\xfe5b', Char
'\xfe5c')
  , (Char
'\xfe5d', Char
'\xfe5e')
  , (Char
'\xff08', Char
'\xff09')
  , (Char
'\xff3b', Char
'\xff3d')
  , (Char
'\xff5b', Char
'\xff5d')
  , (Char
'\xff5f', Char
'\xff60')
  , (Char
'\xff62', Char
'\xff63')
  ]

-- | The list of all brackets characters.
brackets :: [Char]  -- ^ The list of all 'Char's that are brackets.
brackets :: String
brackets = [Char
ci | ~(Char
ca, Char
cb) <- [(Char, Char)]
bracketMaps, Char
ci <- [Char
ca, Char
cb]]

-- | A list of 'Char's that contains all opening brackets.
openBrackets :: [Char]  -- ^ The list of all 'Char's that are /opening brackets/.
openBrackets :: String
openBrackets = ((Char, Char) -> Char) -> [(Char, Char)] -> String
forall a b. (a -> b) -> [a] -> [b]
map (Char, Char) -> Char
forall a b. (a, b) -> a
fst [(Char, Char)]
bracketMaps

-- | A list of 'Char's that contains all closing brackets.
closeBrackets :: [Char]  -- ^ The list of all 'Char's that are /closing brackets/.
closeBrackets :: String
closeBrackets = ((Char, Char) -> Char) -> [(Char, Char)] -> String
forall a b. (a -> b) -> [a] -> [b]
map (Char, Char) -> Char
forall a b. (a, b) -> b
snd [(Char, Char)]
bracketMaps

-- | A 'Map' that maps the given /open bracket/
-- characters to the corresponding /close bracket/.
toClose :: Map Char Char
toClose :: Map Char Char
toClose = [(Char, Char)] -> Map Char Char
forall k a. Ord k => [(k, a)] -> Map k a
fromList [(Char, Char)]
bracketMaps

-- | A 'Map' that maps the given /close bracket/
-- characters to the corresponding /open bracket/.
toOpen :: Map Char Char
toOpen :: Map Char Char
toOpen = [(Char, Char)] -> Map Char Char
forall k a. Ord k => [(k, a)] -> Map k a
fromList (((Char, Char) -> (Char, Char)) -> [(Char, Char)] -> [(Char, Char)]
forall a b. (a -> b) -> [a] -> [b]
map (Char, Char) -> (Char, Char)
forall a b. (a, b) -> (b, a)
swap [(Char, Char)]
bracketMaps)

-- | Check if the given 'Char' is a /bracket/ character.
isBracket
  :: Char -- ^ The given 'Char' to test.
  -> Bool  -- ^ 'True' if the given 'Char' is an open bracket; 'False' otherwise.
isBracket :: Char -> Bool
isBracket Char
c = Map Char Char -> Bool
forall a. Map Char a -> Bool
go Map Char Char
toClose Bool -> Bool -> Bool
|| Map Char Char -> Bool
forall a. Map Char a -> Bool
go Map Char Char
toOpen
  where go :: Map Char a -> Bool
go = Char -> Map Char a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
member Char
c

-- | Check if the given 'Char' is an /open bracket/.
isOpenBracket
  :: Char  -- ^ The given 'Char' to test.
  -> Bool  -- ^ 'True' if the 'Char' is an /open bracket/; 'False' otherwise.
isOpenBracket :: Char -> Bool
isOpenBracket = (Char -> Map Char Char -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`member` Map Char Char
toClose)

-- | Check if the given 'Char' is a /close bracket/.
isCloseBracket
  :: Char  -- ^ The given 'Char' to test.
  -> Bool  -- ^ 'True' if the 'Char' is an /close bracket/; 'False' otherwise.
isCloseBracket :: Char -> Bool
isCloseBracket = (Char -> Map Char Char -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`member` Map Char Char
toOpen)

-- | Check the 'BracketType' of the 'Char' wrapped in a 'Just' data construct;
-- 'Nothing' if the given 'Char' is /not/ a /bracket/ character.
bracketType :: Char -> Maybe BracketType
bracketType :: Char -> Maybe BracketType
bracketType Char
c
  | Map Char Char -> Bool
forall a. Map Char a -> Bool
go Map Char Char
toClose = BracketType -> Maybe BracketType
forall a. a -> Maybe a
Just BracketType
Open
  | Map Char Char -> Bool
forall a. Map Char a -> Bool
go Map Char Char
toOpen = BracketType -> Maybe BracketType
forall a. a -> Maybe a
Just BracketType
Close
  | Bool
otherwise = Maybe BracketType
forall a. Maybe a
Nothing
  where go :: Map Char a -> Bool
go = Char -> Map Char a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
member Char
c

-- | Check the 'BracketType' of the 'Char'. For a 'Char' that is /not/ a /bracket/
-- the behavior is unspecified.
bracketType' :: Char -> BracketType
bracketType' :: Char -> BracketType
bracketType' Char
c
  | Char -> Map Char Char -> Bool
forall k a. Ord k => k -> Map k a -> Bool
member Char
c Map Char Char
toClose = BracketType
Open
  | Bool
otherwise = BracketType
Close

-- | Get the bracket character that is the /counterpart/
-- of the given /bracket/ character wrapped in a 'Just' data
-- constructor. If the given 'Char' is not a bracket, 'Nothing'
-- is returned.
getOppositeChar
  :: Char  -- ^ The given 'Char' for which we want to determine the opposite bracket.
  -> Maybe Char  -- ^ The opposite bracket wrapped in a 'Just' if the given 'Char' is a bracket character; 'Nothing' otherwise.
getOppositeChar :: Char -> Maybe Char
getOppositeChar Char
c = Map Char Char -> Maybe Char
forall a. Map Char a -> Maybe a
go Map Char Char
toClose Maybe Char -> Maybe Char -> Maybe Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Map Char Char -> Maybe Char
forall a. Map Char a -> Maybe a
go Map Char Char
toOpen
  where go :: Map Char a -> Maybe a
go = Char -> Map Char a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
lookup Char
c

-- | Get the bracket character that is the /counterpart/
-- of the given /bracket/ character. If the given 'Char'
-- is not a bracket, the given 'Char' is returned.
getOppositeChar'
  :: Char  -- ^ The given 'Char' for which we want to determine the opposite bracket.
  -> Char  -- ^ The opposite bracket if the given 'Char' is a /bracket/; otherwise the given 'Char'.
getOppositeChar' :: Char -> Char
getOppositeChar' = Char -> Maybe Char -> Char
forall a. a -> Maybe a -> a
fromMaybe (Char -> Maybe Char -> Char)
-> (Char -> Maybe Char) -> Char -> Char
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Char -> Maybe Char
getOppositeChar