From 0d0c3870d945f07e93337c2c2941d85106f807d6 Mon Sep 17 00:00:00 2001 From: Jan Sucan Date: Mon, 20 Mar 2023 16:51:36 +0100 Subject: 4_b_4: Add solution --- ch04/4_b_4.hs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 ch04/4_b_4.hs (limited to 'ch04') diff --git a/ch04/4_b_4.hs b/ch04/4_b_4.hs new file mode 100644 index 0000000..da90d5c --- /dev/null +++ b/ch04/4_b_4.hs @@ -0,0 +1,47 @@ +-- The asInt_fold function uses error, so its callers cannot handle +-- errors. Rewrite it to fix this problem: +-- +-- -- file: ch04/ch04.exercises.hs +-- type ErrorMessage = String +-- asInt_either :: String -> Either String Int +-- +-- ghci> asInt_either "33" +-- Right 33 +-- ghci> asInt_either "foo" +-- Left "non-digit 'o'" + +-- This exercise is based on the previous one (4_b_3.hs). There was only one +-- call to error, so only that call is replaced by Either in this solution. + +-- The example for argument "foo" in the assignment returns 'o' as the first +-- non-digit character. This seems incorrect as the 'f' is the first +-- non-digit. This implementation checks every character other than the minus +-- sign when checking for non-digits. + +import Data.Char (digitToInt, isDigit) + +asInt_either :: String -> Either String Int +asInt_either "" = Right 0 +asInt_either "-" = Right 0 +asInt_either ('-':xs) = propagateEither int + where int = asInt_either' xs + propagateEither (Right x) = Right (-1 * x) + propagateEither left = left +asInt_either xs = asInt_either' xs + +asInt_either' :: String -> Either String Int +asInt_either' xs = foldl nextDigit (Right 0) xs + where nextDigit (Right acc) digit + | not (isDigit digit) = Left ("non-digit '" ++ [digit] ++ "'") + | otherwise = Right ((acc * 10) + (digitToInt digit)) + nextDigit left _ = left + +-- ghci> :l 4_b_4.hs +-- [1 of 1] Compiling Main ( 4_b_4.hs, interpreted ) +-- Ok, one module loaded. +-- ghci> asInt_either "33" +-- Right 33 +-- ghci> asInt_either "foo" +-- Left "non-digit 'f'" +-- ghci> asInt_either "-33" +-- Right (-33) -- cgit v1.2.3