diff options
| author | Jan Sucan <jan@jansucan.com> | 2023-03-20 16:51:36 +0100 |
|---|---|---|
| committer | Jan Sucan <jan@jansucan.com> | 2023-03-20 16:51:36 +0100 |
| commit | 0d0c3870d945f07e93337c2c2941d85106f807d6 (patch) | |
| tree | a7a0b5a97b31e3472daaebe22085131046abd180 | |
| parent | 99af88adc887dc71a458b1698b222e88c10befa7 (diff) | |
4_b_4: Add solution
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | ch04/4_b_4.hs | 47 |
2 files changed, 48 insertions, 1 deletions
@@ -75,7 +75,7 @@ more visible in the list the first exercise of a group is in bold italics. | **_4_b_1_** | yes, in 4_b_2 | 97 | | | 4_b_2 | yes | 98 | | | 4_b_3 | yes | | | -| 4_b_4 | | | | +| 4_b_4 | yes | | | | 4_b_5 | | | | | 4_b_6 | | | | | 4_b_7 | | | | 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) |
