I have written a safe read function for haskell (for education!). I think this is fairly idiomatic haskell code, but I'd like to know for sure. If you see anything else that could be improved, please let me know in your answer. module ReadNum (readNum) wheremain = print $ readNum 87k7readNum :: String -> Maybe IntreadNum xs = readNum' $ reverse xsreadNum' :: String -> Maybe IntreadNum' (x:xs) = (\y z -> y + 10 * z) <$> readChr x <*> readNum' xsreadNum' [] = Just 0chrToNum :: [(Char, Int)]chrToNum = [('0', 0), ('1', 1),            ('2', 2), ('3', 3),            ('4', 4), ('5', 5),            ('6', 6), ('7', 7),            ('8', 8), ('9', 9)]readChr :: Char -> Maybe IntreadChr c = lookup c chrToNum
`read` re-implemented for Int's
strings;parsing;haskell;reinventing the wheel;integer
The change I'd make, respecting your overall design, is to refactor chrToNum as this:chrToNum :: [(Char, Int)]chrToNum = zip 0123456789 [0..]Apart from that, if we are willing to slightly alter the design, I would separate the string validation from the computation of the Int represented. The string validation can be done using mapM :: (a -> m b) -> [a] -> m [b] (this way we avoid explicitly writing the recursion).validateString :: String -> Maybe [Int]validateString = mapM readChrThen, you can define a function computing the Int represented by a list of digits (I use foldl' which requires you to add import Data.List but you can equally well use reverse + foldr as you originally did)represents :: [Int] -> Intrepresents = foldl' (\ ih z -> 10 * ih + z) 0Finally, putting it all together we get:readNum :: String -> Maybe IntreadNum = fmap represents . validateString