{-# LANGUAGE TypeApplications #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} module Lab11a where import Prelude hiding (lookup) import Data.Maybe (fromMaybe) lookup :: Eq a => [(a, b)] -> a -> Maybe b lookup [] _ = Nothing lookup ((key, value):xs) needle | key == needle = Just value | otherwise = lookup xs needle toUpper :: Char -> Char toUpper c = fromMaybe c (lookup toUpperRegistry c) where toUpperRegistry = zip ['a' .. 'z'] ['A' .. 'Z'] toCamelCaseF :: Functor f => f String -> f String toCamelCaseF = fmap toCamelCase where toCamelCase = concat . fmap upperHead . words upperHead (h:t) = toUpper h : t upperHead "" = "" data DFA a = DFA { dfaDelta :: a -> Char -> a , dfaInit :: a , dfaFinal :: a -> Bool } evalDFA :: DFA a -> String -> Bool evalDFA (DFA {..}) input = go input dfaInit where go [] state = dfaFinal state go (c:cs) state = go cs (dfaDelta state c) data FloatStates = Before | Digit | Dot | First | Second | Fail deriving Show floatDfa :: DFA FloatStates floatDfa = DFA { dfaDelta = delta , dfaInit = Before , dfaFinal = final } where isDigit c = c `elem` ['0'..'9'] delta Before c | isDigit c = Digit | otherwise = Fail delta Digit '.' = Dot delta Digit c | isDigit c = Digit | otherwise = Fail delta Dot c | isDigit c = First | otherwise = Fail delta First c | isDigit c = Second | otherwise = Fail delta Second _ = Fail delta Fail _ = Fail final Second = True final _ = False parseNum :: String -> Maybe Float parseNum input | evalDFA floatDfa input = Just (read input) | otherwise = Nothing parseNumF :: Functor f => f String -> f (Maybe Float) parseNumF = fmap parseNum parseIO :: IO Float parseIO = do putStrLn "Enter a number:" line <- getLine case parseNum line of Just f -> pure f Nothing -> parseIO