Difference between revisions of "PFP Laboratory 5"

From Marek Běhálek Wiki
Jump to navigation Jump to search
 
Line 137: Line 137:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BHV96059]]
 
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BHV96059]]
</div>
 
<div style="clear:both"></div>
 
 
== Binary Trees ==
 
* Create a data type <code>Tree</code> that defines binary tree where values are stored in leaves and also in branches.
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
data Tree a = Leaf a
 
            | Branch a (Tree a) (Tree a) deriving (Show)
 
</syntaxhighlight>
 
</div>
 
<div style="clear:both"></div>
 
 
* Prepare an example of a binary tree.
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
testTree1 :: Tree Int           
 
testTree1 = Branch 12 (Branch 23 (Leaf 34) (Leaf 45)) (Leaf 55)
 
 
testTree2 :: Tree Char           
 
testTree2 = Branch 'a' (Branch 'b' (Leaf 'c') (Leaf 'd')) (Leaf 'e')
 
</syntaxhighlight>
 
</div>
 
<div style="clear:both"></div>
 
 
* Create a function that sums all values stored in the tree.
 
<syntaxhighlight lang="Haskell">
 
sum' :: Tree Int -> Int
 
</syntaxhighlight>
 
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
sum' :: Tree Int -> Int
 
sum' (Leaf x) = x
 
sum' (Branch x l r) = sum' l + x + sum' r
 
</syntaxhighlight>
 
</div>
 
<div style="clear:both"></div>
 
 
* Create a function that extracts all values from the tree into an list.
 
<syntaxhighlight lang="Haskell">
 
toList :: Tree a -> [a]
 
</syntaxhighlight>
 
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
toList :: Tree a -> [a]
 
toList (Leaf x) = [x]
 
toList (Branch x l r) = toList l ++ [x] ++ toList r
 
</syntaxhighlight>
 
</div>
 
<div style="clear:both"></div>
 
 
* One possibility how to represent a tree in a textual form is <code>a(b(d,e),c(e,f(g,h)))</code>. Create functions that are able to read and store a tree in such a notation.
 
<div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/b0EF9WQw-uw]]</div>
 
<syntaxhighlight lang="Haskell">
 
toString :: Show a => Tree a -> String
 
fromString :: Read a => String -> Tree a
 
</syntaxhighlight>
 
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
toString :: Show a => Tree a -> String
 
toString (Leaf x) = show x
 
toString (Branch x l r) = show x ++ "(" ++ (toString l) ++ "," ++ (toString r) ++ ")"
 
 
fromString :: Read a => String -> Tree a
 
fromString inp = fst (fromString' inp) where
 
  fromString' :: Read a => String -> (Tree a,String)
 
  fromString' inp =
 
    let
 
      before = takeWhile (\x ->  x /='(' &&  x /=',' &&  x/=')') inp
 
      after = dropWhile (\x ->  x /='(' &&  x /=',' && x/=')') inp
 
      value = read before
 
    in if null after || head after /= '(' then (Leaf value, after) else
 
        let
 
          (l,after') = fromString' (tail after)
 
          (r,after'') = fromString' (tail after')
 
        in (Branch value l r, tail after'')
 
</syntaxhighlight>
 
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>

Latest revision as of 09:42, 30 September 2022

User defined data types and type classes

Video logo.png

Consider following representation of expressions

data Expr = Num Int
          | Add Expr Expr
          | Sub Expr Expr
          | Mul Expr Expr
          | Div Expr Expr
          | Var Char
	  deriving (Eq)
  • Create function eval that evaluates expresions.
Video logo.png
eval :: Expr -> Int
*Main> eval (Add (Num 1) (Num 2))
3
*Main> eval (Mul (Add (Num 1) (Num 2)) (Num 3))
9
eval :: Expr -> Int
eval (Num x) = x
eval (Add l r) =  (eval l) + (eval r)
eval (Sub l r) =  (eval l) - (eval r)
eval (Mul l r) =  (eval l) * (eval r)
eval (Div l r) =  (eval l) `div` (eval r)
Try it!
  • Create function showExpr that shows expression as a String.
Video logo.png
showExpr :: Expr -> String
*Main> showExpr (Add (Num 1) (Num 2))
"1+2"
*Main> showExpr (Mul (Add (Num 1) (Num 2)) (Num 3))
"(1+2)*3"
*Main> showExpr (Mul (Add (Num 1) (Mul (Num 2) (Var 'x'))) (Mul (Num 3) (Var 'x')))
"(1+2*x)*3*x"
*Main> showExpr (Mul (Num 2) (Mul (Var 'x') (Var 'x')))                            
"2*x*x"
showExpr :: Expr -> String
showExpr expr = showExpr' expr NoOp

data Operation = Hi | HiDiv | Lo | LoSub | NoOp deriving (Eq)

showExpr' :: Expr -> Operation -> String
showExpr' (Num x) _ = show x
showExpr' (Var x) _ =  [x]
showExpr' (Add l r) op = let
  x = showExpr' l Lo ++"+"++showExpr' r Lo
  in if op == Hi || op == HiDiv || op==LoSub 
     then "(" ++ x ++")"
     else x
showExpr' (Sub l r) op = let
  x = showExpr' l Lo ++"-"++showExpr' r LoSub
  in if op == Hi || op == HiDiv || op==LoSub 
     then "(" ++ x ++")"
     else x     
showExpr' (Mul l r) op = let
  x = showExpr' l Hi ++"*"++showExpr' r Hi
  in if op == HiDiv
     then "(" ++ x ++")"
     else x
showExpr' (Div l r) op = let
  x = showExpr' l Hi ++"/"++showExpr' r HiDiv
  in if op == HiDiv
     then "(" ++ x ++")"
     else x
Try it!
  • Extend class Show to be usable with our expressions.
Video logo.png
*Main> Add (Num 1) (Num 2)
"1+2"
*Main> Mul (Add (Num 1) (Num 2)) (Num 3)
"(1+2)*3"
*Main> Mul (Add (Num 1) (Mul (Num 2) (Var 'x'))) (Mul (Num 3) (Var 'x'))
"(1+2*x)*3*x"
*Main> Mul (Num 2) (Mul (Var 'x') (Var 'x'))           
"2*x*x"
instance (Show Expr) where
  show = showExpr
Try it!
  • Create function derivation representing symbolic derivation of a given expression.
deriv :: Expr-> Char -> Expr
*Main> deriv (Add (Num 1) (Num 2)) 'x'
0+0
*Main> deriv (Mul (Num 2) (Mul (Var 'x') (Var 'x'))) 'x'
0*x*x+2*(1*x+x*1)
*Main> deriv (Mul (Num 2) (Mul (Var 'x') (Var 'x'))) 'x'
0*x*x+2*(1*x+x*1)
deriv :: Expr-> Char -> Expr
deriv (Num _) _ = (Num 0)     
deriv (Var x) y | x==y = (Num 1)
                | otherwise = (Num 0)
deriv (Add l r) x = Add (deriv l x) (deriv r x)                
deriv (Sub l r) x = Sub (deriv l x) (deriv r x)
deriv (Mul l r) x = Add (Mul (deriv l x) r) (Mul l (deriv r x))
deriv (Div l r) x = 
   Div
    (Sub (Mul (deriv l x) r) (Mul l (deriv r x)))
    (Mul r r)
Try it!