owoify-hs-1.0.0.0: src/Data/Owoify/Internal/Parser/OwoifyParser.hs
{-# LANGUAGE RankNTypes #-}
module Data.Owoify.Internal.Parser.OwoifyParser
( count
, OError(..)
, OwoifyError
, OwoifyParser
, runParser
)
where
import Prelude
import Control.Monad ((>=>), foldM, replicateM)
import Data.Function ((&))
import Data.List (uncons)
import Data.Owoify.Internal.Entity.Word (InnerWord(InnerWord, innerWord, innerReplacedWords))
import Data.Text.Lazy (Text)
-- | Represents those types denoting errors when owoifying.
class OwoifyError e where
-- | Representing that the source collection of strings has been exhausted.
eof :: e
-- | Representing general parser error. Currently not used.
parseError :: Text -> e
-- | A simple type representing errors that occur during owoification.
data OError = EOF | ParseError Text deriving (Show)
instance OwoifyError OError where
eof = EOF
parseError = ParseError
type OwoifyResult a = ([Text], a)
type OwoifyFunction e a = OwoifyError e => [Text] -> Either e (OwoifyResult a)
newtype OwoifyParser e a = OwoifyParser (OwoifyFunction e a)
instance Functor (OwoifyParser e) where
fmap f (OwoifyParser g) = OwoifyParser (fmap (fmap f) . g)
instance Applicative (OwoifyParser e) where
(<*>) (OwoifyParser f) (OwoifyParser g) = OwoifyParser (f >=> \(s', ab) -> g s' >>= \(s'', a) -> pure (s'', ab a))
pure x = OwoifyParser (\s -> pure (s, x))
instance Monad (OwoifyParser e) where
(>>=) (OwoifyParser f) g = OwoifyParser (f >=> \(s', a) -> runParser (g a) s')
-- | Executes (unwraps) the parser inside the monad.
runParser :: OwoifyError e => OwoifyParser e a -> [Text] -> Either e (OwoifyResult a)
runParser (OwoifyParser f) = f
word ::
(Foldable t, Monad m, OwoifyError e)
=> t (InnerWord -> m InnerWord)
-> OwoifyParser e (m InnerWord)
word mappings = OwoifyParser (\s ->
case uncons s of
Nothing -> Left eof
Just (head, tail) -> do
let w = InnerWord { innerWord = head, innerReplacedWords = [] }
let result = foldM (&) w mappings
Right (tail, result))
-- | Replicate owoify parser according to the specified length (`n`) and a collection of owoify functions.
count ::
(Foldable t, Monad m, OwoifyError e)
=> Int
-> t (InnerWord -> m InnerWord)
-> OwoifyParser e [m InnerWord]
count n p | n <= 0 = pure []
| otherwise = replicateM n $ word p