From ef81a4014ba5e58aa86842e9b1161335d306ca98 Mon Sep 17 00:00:00 2001 From: Jan Sucan Date: Sun, 19 Mar 2023 19:16:24 +0100 Subject: 4_b_1 and 4_b_2: Add solutions --- README.md | 4 ++-- ch04/4_b_2.hs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 ch04/4_b_2.hs diff --git a/README.md b/README.md index 3f1ecff..238d718 100644 --- a/README.md +++ b/README.md @@ -72,8 +72,8 @@ more visible in the list the first exercise of a group is in bold italics. | 4_a_2 | yes | | | | 4_a_3 | yes | | | | 4_a_4 | yes | | | -| **_4_b_1_** | | 97 | | -| 4_b_2 | | 98 | | +| **_4_b_1_** | yes, in 4_b_2 | 97 | | +| 4_b_2 | yes | 98 | | | 4_b_3 | | | | | 4_b_4 | | | | | 4_b_5 | | | | diff --git a/ch04/4_b_2.hs b/ch04/4_b_2.hs new file mode 100644 index 0000000..ff92cf9 --- /dev/null +++ b/ch04/4_b_2.hs @@ -0,0 +1,47 @@ +-- 1. Use a fold (choosing the appropriate fold will make your code much +-- simpler) to rewrite and improve upon the asInt function from the earlier +-- section called "Explicit recursion" on page 85. +-- +-- -- file: ch04/ch04.exercises.hs +-- asInt_fold :: String -> Int +-- +-- 2. Your function should behave as follows: +-- +-- ghci> asInt_fold "101" +-- 101 +-- ghci> asInt_fold "-31337" +-- -31337 +-- ghci> asInt_fold "1798" +-- 1798 + +import Data.Char (digitToInt) + +-- If we used foldr, it would have needed to reconstruct position of the digit +-- processed in the step function (here nextDigit). When digits are processed +-- from right to left, we need to know position of the digit in the number so we +-- can multiply it by the corresponding power of 10 before adding it to the +-- accumulator. The information about the position would have to be gotten from +-- a value already in the accumulator. +-- +-- With foldl, when digits are processed from left to right, the information +-- about the position is not needed. We just multiply the accumulator by ten to +-- shift the decimal value to the left, thus making room for one more digit, and +-- then add value of that digit to the accumulator. + +asInt_fold :: String -> Int +asInt_fold ('-':xs) = -1 * (asInt_fold' xs) +asInt_fold xs = asInt_fold' xs + +asInt_fold' :: String -> Int +asInt_fold' xs = foldl nextDigit 0 xs + where nextDigit acc digit = (acc * 10) + (digitToInt digit) + +-- ghci> :l 4_b_2.hs +-- [1 of 1] Compiling Main ( 4_b_2.hs, interpreted ) +-- Ok, one module loaded. +-- ghci> asInt_fold "101" +-- 101 +-- ghci> asInt_fold "-31337" +-- -31337 +-- ghci> asInt_fold "1798" +-- 1798 -- cgit v1.2.3