Finish Homework 2
This commit is contained in:
parent
3f673113b7
commit
93604a3c07
98
HW2.fedorind.hs
Normal file
98
HW2.fedorind.hs
Normal file
|
@ -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
|
Loading…
Reference in New Issue
Block a user