module Codewars.Kata.Braces where import Control.Monad ((>=>)) import Control.Applicative ((<|>)) newtype Validator = Validator { check :: String -> Maybe String } validChar :: Char -> Validator validChar c = Validator v where v (c' : rest) | c' == c = Just rest v _ = Nothing fail :: Validator fail = Validator $ const Nothing pass :: Validator pass = Validator Just andThen :: Validator -> Validator -> Validator v1 `andThen` v2 = Validator $ check v1 >=> check v2 orElse :: Validator -> Validator -> Validator v1 `orElse` v2 = Validator $ \s -> check v1 s <|> check v2 s some :: Validator -> Validator some v = v `andThen` many v many :: Validator -> Validator many v = some v `orElse` pass wrapped :: Char -> Char -> Validator -> Validator wrapped l r v = validChar l `andThen` v `andThen` validChar r wrappedRound :: Validator -> Validator wrappedRound = wrapped '(' ')' wrappedSquare :: Validator -> Validator wrappedSquare = wrapped '[' ']' wrappedCurly :: Validator -> Validator wrappedCurly = wrapped '{' '}' balancedOnce :: Validator balancedOnce = wrappedRound pass `orElse` wrappedSquare pass `orElse` wrappedCurly pass `orElse` wrappedRound more `orElse` wrappedSquare more `orElse` wrappedCurly more where more = some balancedOnce validBraces :: String -> Bool validBraces = maybe False (== []) . check (many balancedOnce)