asInt_either
Real World Haskell, Exercise 4, p. 98:
The asInt_fold function uses error, so its callers cannot handle errors. Rewrite it to fix this problem.
-- file: ch04/IntParse.hs
import Data.Char (digitToInt)
asInt :: String -> Int
asInt ('-':xs) = -1 * asInt xs
asInt xs = foldl step 0 xs
where step acc x = acc * 10 + safeDigitToInt x
safeDigitToInt :: Char -> Int
safeDigitToInt x = if x >= '0' && x <= '9'
then digitToInt x
else error "Non-digit"
asInt_either :: String -> Ei
asInt_either xs = if onlyHasDigits xs
then Main.Right (asInt xs)
else Main.Left ("non-digit '" ++ ((firstNonDigit xs) : "'"))
onlyHasDigits :: String -> Bool
onlyHasDigits [] = True
onlyHasDigits (x:xs) = if x >= '0' && x <= '9'
then onlyHasDigits xs
else False
firstNonDigit :: String -> Char
firstNonDigit [] = '\0'
firstNonDigit (x:xs) = if x <= '0' || x >= '9'
then x
else firstNonDigit xs
data Ei = Right Int
| Left String
deriving (Show)
Doubtless this could be much mproved by someone who knows what they’re doing.
January 21st, 2009 at 2:12 AM
It seems better for firstNonDigit [] to throw an error, given that you never expect it to be called, and silently returning a null character will probably cause much confusion if it ever actually happens.
January 21st, 2009 at 9:42 AM
Actually, I could just delete it, I think.
One thing that bothers me, probably just because I don’t know enough Haskell yet, is how to mark a function “private”. That is, I want to only allow the function to be called from within the same source file. Of course, I could just inline the function, but this is hard enough to read as is.
January 21st, 2009 at 5:38 PM
I’m not a Haskell expert, but it seems that modules export everything by default, unless you explicitly list which symbols you wish to export. Personally I prefer the approach taken by Mercury, in which each module has an interface section and an implementation section, much like a C header file followed by its implementation. I find that more elegant than Java, in which public and private methods and method bodies are all intertwingled, and getting a high-level overview of the class is easier from the generated API docs.
February 5th, 2009 at 4:30 PM
The Java approach, though, has the strengths of its weaknesses: you can easily see, looking at a given method or whatever, whether it’s public or private. Keeping that information near the top is good for a module-level overview, but easy to get wrong at the level of writing methods.