diff --git a/HW1.md b/HW1.md new file mode 100644 index 0000000..fa178d0 --- /dev/null +++ b/HW1.md @@ -0,0 +1,83 @@ +**Andrew\'s solution**: + +(Hi Andrew! Long time since databases) + +This solution is straightforward and simple, and is similar to +Nicholas\'. Just like all the other solutions, it pattern matches on the +arguments (instead of using \"case\" expressions), and uses the Prelude +functions. Everything\'s idiomatic, but I think that the last function +(\"pretty\") can use an improvement. Here\'s the code in question: + + pretty (Mul l r) = a ++ " * " ++ b + where + a = case l of + (Add _ _) -> parens True (pretty l) + _ -> parens False (pretty l) + b = case r of + (Add _ _) -> parens True (pretty r) + _ -> parens False (pretty r) + +Here, the code for \"a\" and \"b\" is almost identical, and uses an +unneeded auxiliary function. For one thing, you can merge the two +variables \"a\" and \"b\" into a function: + + pretty (Mul l r) = wrap l ++ " * " ++ wrap r + where + wrap e = case e of + (Add _ _) -> parens True (pretty e) + _ -> parens False (pretty e) + +Then, you can fuse the definition of \"parens\" with the definition of +\"wrap\" (passing booleans to functions is actually a code smell, see +[the boolean identity +crisis](https://programming-elm.com/blog/2019-05-20-solving-the-boolean-identity-crisis-part-1/)): + + pretty (Mul l r) = wrap l ++ " * " ++ wrap r + where + parens e@(Add _ _) = "(" ++ pretty e ++ ")" + parens e = pretty e + +**Nicholas\' solution** + +This is another straightforward and idiomatic solution. The \"pretty\" +function is conservative, unlike Andrew\'s,  but requires little code. + +**Shu-Kan\'s solution** + +The parenthesis placement is a little off in this one, and it doesn\'t +use built-in functions like \'max\', which could have been used in +maxLit. It also seems to import data.Typeable, which I don\'t really see +used here. To improve it, take a look at these lines: + + maxLit (Add(x)(y)) = if maxLit(x) > maxLit(y) then maxLit(x) else maxLit(y) + maxLit (Mul(x)(y)) = if maxLit(x) > maxLit(y) then maxLit(x) else maxLit(y) + +In Haskell, function application is written with a space: \"f x\" +instead of \"f(x)\". Writing \"maxLit(y)\" is equivalent to writing +\"maxLit (y)\". But then, you don\'t even need parentheses! + + maxLit (Add x y) = if maxLit x > maxLit y then maxLit x else maxLit y + maxLit (Mul x y) = if maxLit x > maxLit y then maxLit x else maxLit y + +Finally, the \"if x \> y then x else y\" idiom is just the \"max\" +function in Haskell\'s Prelude: + + maxLit (Add x y) = max (maxLit x) (maxLit y) + maxLit (Mul x y) = max (maxLit x) (maxLit y) + +**My solution** + +I went a weird route. For one, I created a Num instance for Expr, so +that I could write expressions as \"3\*2\" instead of \"Mul (Lit 3) (Lit +2)).  This definition is incomplete; it\'s missing the abs, negate, and +signum functions. However, it does make for funny definitions, and +handles precedence for me! + +In addition, I wrote a \"fold\" function for the Expr data type, and +wrote all functions except for \"pretty\" using it. They ended up pretty +short: + + leftLit = fold id const const + rightLit = fold id (flip const) (flip const) + maxLit = fold id max max + eval = fold id (+) (*)