Created
May 9, 2025 14:38
-
-
Save Icelandjack/bfc5de19e82f98f423b8f72dc35872f3 to your computer and use it in GitHub Desktop.
Revisions
-
Icelandjack created this gist
May 9, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,80 @@ -- | parseAlt "ok| -- -- > parseAlt "one|two|three" `runParser` "four!" -- Right ("","four!") -- > parseAlt "one|two|three" `runParser` "one!" -- Right ("one","!") parseAlt :: forall (regexp :: Symbol) -> ParseAlt regexp => Parser String parseAlt regexp = parseAlt' @(SplitPipe (ToList regexp)) -- | Implementation newtype Parser a = Parser { runParser :: String -> Either String (a, String) } deriving (Functor, Applicative, Monad, Alternative) via StateT String (Either String) satisfy :: (Char -> Bool) -> Parser Char satisfy p = Parser \case c:cs | p c -> Right (c, cs) _ -> Left "satisfy: input does not match predicate or is empty" char :: Char -> Parser Char char c = satisfy (== c) type ToList :: Symbol -> [Char] type ToList symbol = ToList' (UnconsSymbol symbol) type ToList' :: Maybe (Char, Symbol) -> [Char] type family ToList' maybe where ToList' Nothing = '[] ToList' (Just '(ch, str)) = ch : ToList str type SplitPipe :: [Char] -> [[Char]] type family SplitPipe chars where SplitPipe chars = SplitPipe' (BreakPipe chars) type SplitPipe' :: ([Char], [Char]) -> [[Char]] type family SplitPipe' pair where SplitPipe' '(as, '[]) = '[as] SplitPipe' '(as, '|':bs) = as : SplitPipe bs type BreakPipe :: [Char] -> ([Char], [Char]) type family BreakPipe as where BreakPipe '[] = '( '[], '[] ) BreakPipe ('|':as) = '( '[], '|':as ) BreakPipe (a:as) = Cons a (BreakPipe as) type Cons :: a -> ([a], [a]) -> ([a], [a]) type family Cons x pair where Cons a '(as, bs) = '(a:as, bs) type ParseAlt :: Symbol -> Constraint type ParseAlt as = ParseAlt' (SplitPipe (ToList as)) type ParseAlt' :: [[Char]] -> Constraint class ParseAlt' charss where parseAlt' :: Parser String instance ParseAlt' '[] where parseAlt' = pure "" instance (ParseStr c, ParseAlt' cs) => ParseAlt' (c:cs) where parseAlt' = parseStr @c <|> parseAlt' @cs type ParseStr :: [Char] -> Constraint class ParseStr chars where parseStr :: Parser String instance ParseStr '[] where parseStr :: Parser String parseStr = pure "" instance (KnownChar char, ParseStr chars) => ParseStr (char:chars) where parseStr :: Parser String parseStr = liftA2 (:) (char (charVal @char Proxy)) (parseStr @chars)