Homework/HW2.fedorind.hs

99 lines
2.5 KiB
Haskell
Raw Normal View History

2020-10-01 17:46:28 -07:00
-- | 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
2020-10-01 17:46:28 -07:00
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 "*")
2020-10-01 17:46:28 -07:00
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 :^)
2020-10-01 17:46:28 -07:00
-- | 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
--
2020-10-07 16:12:14 -07:00
sub = (. neg) . Add -- (a -> b) is a Functor