-- Semi-Isomorphism for specific characters
onlyChar :: Char -> Iso Char Char
onlyChar c = iso check check where
    check input = if input == c
        then Just c
        else Nothing

----------------------------------------------------------------------------------------------------
{-  A haskell functor is covariant:
        fmap :: forall f a b. (Functor f) => (a -> b) -> f a -> f b

    This works for parsers, e.g.:
        newtype Parser a = Parser { _parse :: String -> a }
        instance Functor Parser where
            fmap :: forall a b. (a -> b) -> Parser a -> Parser b
            fmap f (Parser p) = Parser (f . p)
-}

{-  Pretty-printers on the other hand are contravariant:
        cofmap :: forall f a b. (Contravariant f) => (a -> b) -> f b -> f a

    E.g.:
        newtype Printer a = Printer { _print :: a -> String }
        instance Contravariant Printer where
            contramap :: forall a b. (a -> b) -> Printer b -> Printer a
            contramap f (Printer p) = Printer (p . f)
-}

{-  In order to get both, we can simply apply an isomorphism instead of a function:
-}
onlyChar :: Char -> Iso Char Char
onlyChar c = iso check check where
    check input = if input == c
        then Just c
        else Nothing

----------------------------------------------------------------------------------------------------
{-  A haskell functor is covariant:
        fmap :: forall f a b. (Functor f) => (a -> b) -> f a -> f b

    This works for parsers, e.g.:
        newtype Parser a = Parser { _parse :: String -> a }
        instance Functor Parser where
            fmap :: forall a b. (a -> b) -> Parser a -> Parser b
            fmap f (Parser p) = Parser (f . p)
-}

{-  Pretty-printers on the other hand are contravariant:
        cofmap :: forall f a b. (Contravariant f) => (a -> b) -> f b -> f a

    E.g.:
        newtype Printer a = Printer { _print :: a -> String }
        instance Contravariant Printer where
            contramap :: forall a b. (a -> b) -> Printer b -> Printer a
            contramap f (Printer p) = Printer (p . f)
-}

{-  In order to get both, we can simply apply an isomorphism instead of a function:
-}
onlyChar c = iso check check where
    check input = if input == c
        then Just c
        else Nothing

----------------------------------------------------------------------------------------------------
{-  A haskell functor is covariant:
        fmap :: forall f a b. (Functor f) => (a -> b) -> f a -> f b

    This works for parsers, e.g.:
        newtype Parser a = Parser { _parse :: String -> a }
        instance Functor Parser where
            fmap :: forall a b. (a -> b) -> Parser a -> Parser b
            fmap f (Parser p) = Parser (f . p)
-}

{-  Pretty-printers on the other hand are contravariant:
        cofmap :: forall f a b. (Contravariant f) => (a -> b) -> f b -> f a

    E.g.:
        newtype Printer a = Printer { _print :: a -> String }
        instance Contravariant Printer where
            contramap :: forall a b. (a -> b) -> Printer b -> Printer a
            contramap f (Printer p) = Printer (p . f)
-}

{-  In order to get both, we can simply apply an isomorphism instead of a function:
-}