binary tree in generalized statement - haskell

I have to implement a Code which accepts a binary tree and shows a generalised Statement: this is my Code
mkBTree xs
| (m == 0) = Leaf (unwrap xs)
| otherwise = Fork (mkBTree ys) (mkBTree zs)
where m = (length xs) `div` 2
(ys, zs) = splitAt m xs
unwrap [x] = x
but the only thing i get is something like:
Data constructor not in scope: Leaf :: a -> t
Data constructor not in scope: Fork :: t -> t -> t
Failed, modules loaded: none.
What is wrong here?

I have to implement a Code which accepts a binary tree and shows a generalised Statement: this is my Code import Data.Char
import Data.List
data mkBTree xs = Leaf xs | Fork (mkBTree xs) xs (mkBTree xs)
deriving(Eq,Show)
data mkBTree xs = Leaf xs | Fork xs [mkBTree xs]
deriving(Eq,Show)
entferneBlaetter :: NBaum a -> NBaum a
entferneBlaetter xs
| (m == 0) = BBlatt (unwrap xs)
| otherwise = BKnoten (NBaum ys) (NBaum zs)
where m = (length xs) `div` 2
(ys, zs) = splitAt m xs
unwrap [x] = x

Related

Is there a way to use "<=" for pattern matching in Haskell?

I have the following code, that drops every nth element in a list.
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys 0 = []
f ys 1 = []
f [] m = []
f (y:ys) n = y : (f ys (n-1))
I would like to make it a bit shorter and was wondering if there is a way to use "<=" in pattern matching. I tried doing this using a where clause, which did not work, why?
f ys m = []
where
m <= 1 || ys == []
How can I shirk this redundancy? Is there a nice way to use "less or equal" in pattern matching?
EDIT: I tried this using guards
where
f ys m
| m <= 1 || null ys = []
| otherwise = (head ys) : (f (tail ys) (n-1))
You can work with a guard:
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys i | i <= 1 = []
f [] _ = []
f (y:ys) n = y : (f ys (n-1))
If the condition in the guard is satisfied, then that clause "fires" and thus in this case will return an empty list [].
You will however get stuck in an infinite loop, since you write f xs n ++ dropEvery (n xs) n but drop 3 [] will return [], and thus it will keep calling dropEvery with an empty list.
You can make use of recursion where we each time decrement n until it reaches 0, and then we make two hops, so:
dropEvery :: Int -> [a] -> [a]
dropEvery n = go (n-1)
where go _ [] = []
go i (x:xs)
| i <= 0 = go (n-1) xs
| otherwise = x : go (i-1) xs
We can also work with splitAt :: [a] -> ([a], [a]) and with a pattern guard:
dropEvery n [] = []
dropEvery n ds
| (_:ys) <- sb = sa ++ dropEvery n ys
| otherwise = sa
where (sa, sb) = splitAt (n-1) ds

Couldn't match expected type `[a1]' with actual type `([a1], [a1])'

I am new to coding with Haskell and am stuck on this code that my professor wanted us to write. I am supposed to deal a single list into a pair of lists like so:
deal [1,2,3,4,5,6,7] = ([1,3,5,7], [2,4,6])
but I am getting this error on my 'xs' and also 'ys'
* Couldn't match expected type `[a1]'
with actual type `([a1], [a1])'
* In the expression: deal xs
In an equation for `xs': xs = deal xs
In an equation for `deal':
deal (x : y : xs : ys)
= (x : xs, y : ys)
where
xs = deal xs
ys = deal ys
* Relevant bindings include xs :: [a1] (bound at lab2.hs:16:17)
|
| xs = deal xs
| ^^^^^^^
Here is my code:
deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:xs:ys) = (x:xs,y:ys)
where
xs = deal xs
ys = deal ys
This is logical, since here your deal xs and deal ys will return, given the signature a 2-tuple of lists, and xs has type [a]. Note that by using the same name, you here made a recursive expression, which will not work. Using the same name multiple times is not a good idea. If you turn on warnings, the compiler will normally warn against that.
You probably want to call deal on the rest of the list, and then retrieve the two lists that you use as tails:
deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:rest) = (x:xs, y:ys)
where (xs, ys) = deal rest
or we can make use of (***) :: a b c -> a b' c' -> a (b, b') (c, c'):
import Control.Arrow((***))
deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal [x] = ([x], [])
deal (x:y:rest) = ((x:) *** (y:)) (deal rest)
an alternative is to each time swap the tuple, and append to the other side:
import Control.Arrow(first)
import Data.Tuple(swap)
deal :: [a] -> ([a],[a])
deal [] = ([], [])
deal (x:xs) = first (x:) (swap (deal xs))
we can thus define this as a foldr pattern:
import Control.Arrow(first)
import Data.Tuple(swap)
deal :: Foldable f => f a -> ([a],[a])
deal [] = foldr ((. swap) . first . (:)) ([], [])
This gives us the expected result:
Prelude> deal [1,2,3,4,5,6,7]
([1,3,5,7],[2,4,6])

haskell mergesort implementation compiles but does not return anything

Here is my implementation:
mergesort :: (Ord a) => [a] -> [a]
mergesort list = merge (mergesort (left list)) (mergesort (right list))
where
left xs = take (div (length xs) 2) xs
right xs = drop (div (length xs) 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
The code compiles but when I run it my machine crashes. What am I doing wrong?
You are missing base cases - so you get infinite recursion. Trying stepping through your example with lists like [] or [1] and you'll fall straight into the problem.
mergesort :: (Ord a) => [a] -> [a]
mergesort [] = [] -- < ADDED
mergesort [x] = [x] -- < ADDED
mergesort list = merge (mergesort (left list)) (mergesort (right list))
where
left xs = take (div (length xs) 2) xs
right xs = drop (div (length xs) 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys

Haskell: How to use let-in construction?

I wrote a sort function. It's pretty weird.
sort :: (Eq a, Ord a) => [a] -> [a]
sort xs = repeat'' sort' (xs) (length xs)
repeat'' f xs 0 = xs
repeat'' f xs n = repeat'' f (f xs) (n-1)
sort' (x:y:xs)
| x < y = y : sort' (x:xs)
| otherwise = x : sort' (y:xs)
sort' x = x
How can I prettify it using let-in construction?
I think my try doesn't look good:
sort :: (Eq a, Ord a) => [a] -> [a]
sort xs = let
r f xs 0 = xs
r f xs n = r f (f xs) (n-1)
in r f' xs $ length xs where
f' (x:y:xs) | x < y = y : f' (x:xs)
| otherwise = x : f' (y:xs)
f' a = a

Haskell : Comparing if two binary trees have the same elements

So I am working on a function that detects if two binary trees have the same numbers in them.
So what I've come up with is the following which works just fine but the problem is that I am using total of 5 functions. Is there another way of detecting if two BT's have the same elements with just one function ? Here is my solution so far which seems to work just fine.
flatten :: BinTree a -> [a]
flatten Empty = []
flatten (Node l x r) = flatten l ++ [x] ++ flatten r
splt :: Int -> [a] -> ([a], [a])
splt 0 xs = ([], xs)
splt _ [] = ([],[])
splt n (x:xs) = (\ys-> (x:fst ys, snd ys)) (splt (n-1) xs)
merge :: Ord a => [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = if (x > y) then y:merge (x:xs) ys else x:merge xs(y:ys)
msort :: Ord a => [a] -> [a]
msort [] =[]
msort (x:[]) = (x:[])
msort xs = (\y -> merge (msort (fst y)) (msort (snd y))) (splt (length xs `div` 2) xs)
areTreesEqual :: (Ord a) => BinTree a -> BinTree a-> Bool
areTreesEqual Empty Empty = True
areTreesEqual Empty a = False
areTreesEqual a Empty = False
areTreesEqual a b = msort (flatten (a) ) == msort (flatten (b))
How about
import Data.MultiSet as Set
equal a b = accum a == accum b
where accum Empty = Set.empty
accum (Node l x r) = Set.insert x (accum l `Set.union` accum r)
Sets are lovely for unordered comparison and multisets will make sure that
1 /= 1
1 1
Eg, that duplicate numbers are counted properly. If this isn't a big concern, than swap MultiSet for Set. I think 3 lines is pretty decent for this sort of thing.

Resources