`read` re-implemented for Int's 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) where

main = print $ readNum "87k7"

readNum :: String -&gt; Maybe Int
readNum xs = readNum' $ reverse xs

readNum' :: String -&gt; Maybe Int
readNum' (x:xs) = (\y z -&gt; y + 10 * z) &lt;$&gt; readChr x &lt;*&gt; readNum' xs
readNum' [] = Just 0

chrToNum :: [(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 -&gt; Maybe Int
readChr c = lookup c chrToNum
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 -&gt; m b) -&gt; [a] -&gt; m [b] (this way we avoid explicitly writing the recursion).

validateString :: String -&gt; Maybe [Int]
validateString = mapM readChr


Then, 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] -&gt; Int
represents = foldl' (\ ih z -&gt; 10 * ih + z) 0


Finally, putting it all together we get:

readNum :: String -&gt; Maybe Int
readNum = fmap represents . validateString