aboutsummaryrefslogtreecommitdiff
path: root/ch04
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2023-03-19 19:16:24 +0100
committerJan Sucan <jan@jansucan.com>2023-03-19 19:16:24 +0100
commitef81a4014ba5e58aa86842e9b1161335d306ca98 (patch)
tree4231363638e939e519ad855483e2375fa3e70365 /ch04
parent0f49230b9bc7da4a1c5f77e88141cb49c776c398 (diff)
4_b_1 and 4_b_2: Add solutions
Diffstat (limited to 'ch04')
-rw-r--r--ch04/4_b_2.hs47
1 files changed, 47 insertions, 0 deletions
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