`unwordsList :: [LispVal] -> String` composes three functions:
* `map :: (a -> b) -> [a] -> [b]` a function with two "arguments"[0], a
function `(a -> b)` and a list of `a`s (`[a]`) and returns a `[b]`, i.e.
it applies the function in the first argument to every element of the
second
* `showAll :: LispVal -> String` described in the previous commit.
`map showAll` returns a function that applies `showAll` to each
element of the list it gets.
* `unwords :: [String] -> String` which joins a list of Strings with
spaces.
The `.` dot operator is used to pass the output of rhs to the input of
lhs. So in essence, `unwordsList` is a function that will `unword` the
list of Strings returned by `map`ing `showVal` to the list of `LispVal`s
passed to `unwordsList`.
[0] Remember that all functions are curried, and actually only take one
argument and return a "partial function" that takes the next argument.
showVal :: LispVal -> String
showVal (Atom atom) = atom
+showVal (List list) = "(" ++ unwordsList list ++ ")"
+showVal (DottedList head tail) = "(" ++ unwordsList head ++ " . " ++ showVal tail ++ ")"
showVal (Number n) = show n
showVal (String str) = "\"" ++ str ++ "\""
showVal (Character c) = "'" ++ [c] ++ "'"
showVal (Bool True) = "#t"
showVal (Bool False) = "#f"
+unwordsList :: [LispVal] -> String
+unwordsList = unwords . map showVal
+
main :: IO ()
main = do
args <- getLine