From 93604a3c07a4252b0ecca01b33a5f3cb01bc34ef Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Thu, 1 Oct 2020 17:46:28 -0700 Subject: [PATCH] Finish Homework 2 --- HW2.fedorind.hs | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 HW2.fedorind.hs diff --git a/HW2.fedorind.hs b/HW2.fedorind.hs new file mode 100644 index 0000000..deeead6 --- /dev/null +++ b/HW2.fedorind.hs @@ -0,0 +1,98 @@ +-- | Homework 2 template. See the homework description page for more details, +-- hints, and things to think about for each part. +module HW2 where + +import HW1 + +-- Copied from my HW1 for your convenience! +fold :: (Int -> a) -> (a -> a -> a) -> (a -> a -> a) -> Expr -> a +fold f1 f2 f3 = rec + where + rec (Lit i) = f1 i + rec (Add l r) = f2 (rec l) (rec r) + rec (Mul l r) = f3 (rec l) (rec r) + +-- +-- * Part 1: Reverse Polish Notation +-- + +-- | Takes an expression and returns a string encoding of that expression in +-- Reverse Polish Notation (RPN). +-- +-- >>> toRPN (Lit 3) +-- "3" +-- +-- >>> toRPN e1 +-- "2 3 4 * +" +-- +-- >>> toRPN e2 +-- "7 6 + 5 *" +-- +-- >>> toRPN e3 +-- "3 2 * 5 4 * +" +-- +-- >>> elem (toRPN e4) ["8 7 9 * + 6 +", "8 7 9 * 6 + +"] +-- True +-- +toRPN :: Expr -> String +toRPN = fold show (rpn "+") (rpn "*") + where rpn op l r = concat [l, " ", r, " ", op] + + +-- | Takes a string that is an RPN-encoded expression and produces the same +-- expression represented as an abstract syntax tree. +-- +-- You can assume that your function will only be given valid RPN-encodings +-- of expressions. That is, it need not fail gracefully if it encounters an +-- error. However, if you would like to improve the error handling, you are +-- welcome to change the type of your function and the doctests. +-- +-- >>> fromRPN "3" +-- Lit 3 +-- +-- >>> fromRPN "2 3 +" +-- Add (Lit 2) (Lit 3) +-- +-- >>> fromRPN "2 3 4 + +" +-- Add (Lit 2) (Add (Lit 3) (Lit 4)) +-- +-- >>> all (\e -> e == fromRPN (toRPN e)) [e1,e2,e3,e4] +-- True +-- +fromRPN :: String -> Expr +fromRPN = head . foldl step [] . words + where + step (l:r:es) "+" = (Add r l):es + step (l:r:es) "*" = (Mul r l):es + step es s = (Lit (read s)):es + + +-- +-- * Part 2: Syntactic Sugar +-- + +-- | Takes an expression and returns an expresion that evaluates to its +-- negation. Notice that this function does *not* evaluate the expression! +-- It returns a new expression that, when evaluated, will evaluate to the +-- negation of the original expression. +-- +-- >>> eval e2 +-- 65 +-- +-- >>> eval (neg e2) +-- -65 +-- +neg = fold (Lit . negate) Add (Mul . neg) -- Not efficient, but short :^) + + +-- | Takes two expressions and returns an expression that evalautes to the +-- second expression subtracted from the first. Once again, note that the +-- return type is an expression. +-- +-- >>> eval e1 +-- 14 +-- +-- >>> eval (sub e2 e1) +-- 51 +-- +sub = fmap (. neg) Add -- (a -> b) is a Functor