Haskell Binary Tree with only chars - haskell

Lets say I make my tree like this
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
But I want to make a tree that uses only chars I don't need it to be template. I know my tree will use only chars if I make it like the one above I can't make if dataOfNode == ')' in a function because It says that it is a [char] type and it expects [a] type.
How to make a tree that would use only chars or is there a way to make this type of check dataOfNode == ')' with this type of tree that I gave. Can you give me a short example of a function that let's say check if the data in this node is the sign ')' ?
Edit:
As requested I am posting the function that I would like to make `
buildTreeHelper :: (Ord a) => String -> a -> Int -> String -> Tree a -> Tree a
buildTreeHelper str blank turn path t
| str == [] = t
| front == '(' = buildTreeHelper (tail str) blank 1 ('L':path) (expandTree (reverse path) blank t)
| front == ')' = buildTreeHelper (tail str) blank 2 (tail path) t
| turn == 1 = buildTreeHelper (tail str) blank 2 (tail path) (expandTree (reverse path) front t)
| turn == 2 = buildTreeHelper (tail str) blank 3 ('R':path) (expandTree (reverse path) front t)
| turn == 3 = buildTreeHelper (tail str) blank 2 (tail path) (expandTree (reverse path) front t)
where
front = head str
Logically it is not finished but also I can't use it because it takes a string which I divade char by char. That's why I am sure I want to make my Tree only from chars so I can replace type a with type char at the begining of the function. It has other mistakes too but I think the main idea is clear.

You easily could replace your type definition with
data Tree = EmptyTree | Node Char Tree Tree deriving (Show, Read, Eq)
or specialise just your function defining it as
buildTreeHelper :: String -> Char -> Int -> String -> Tree Char -> Tree Char

Related

can i use a string as a whole string after cutting it to head and tails (a:as) and using recursion on it in Haskell?

I am trying to use every character in the string in a function i have (that uses only one Char) but i am also trying to use that same string as a whole in the same recursive function to compare it to indvidual characters in another string (using elem). Is there a way i can use that string heads and tails and also the whole string, so that the string will not be cut after every recursion?
Code:
checkTrue :: TrueChar -> Char -> [Char] -> TruthValue
checkTrue a b c
| a == IsTrue b = AbsoluteTrue
| (a == IsFalse b) && (b `elem` c) = PartialTrue
| otherwise = NoneTrue
checkTruths :: [TrueChar] -> [Char] -> [TruthValue]
checkTruths [][] = []
checkTruths (a:as) (b:bs) = checkTrue a b (removeAbsoluteTrue (a:as) (b:bs)): checkTruths as bs
{- This is the line,
i wanted to use b as a string and also as b:bs. is this possible? -}
checkTruths _ _ = [NoneTrue]
You want an as-pattern, as documented in Section 3.17.1 of the Haskell 2010 report.
Patterns of the form var#pat are called as-patterns, and allow one to
use var as a name for the value being matched by pat. For example,
case e of { xs#(x:rest) -> if x==0 then rest else xs }
is equivalent
to:
let { xs = e } in
case xs of { (x:rest) -> if x==0 then rest else xs }
In your function, you'd write
checkTruths alla#(a:as) allb#(b:bs) = checkTrue a b (removeAbsoluteTrue alla allb): checkTruths as bs

Modifying a list using recursion

I have a list with elements of type LocalType (defined below), I wish to modify this list in function of which subtptype the element is belonging too.
An element of type End stays in the list of type End. For an element of type Prl (End Bar End), the first End shall stay in the list, the second End shall be appended to the list.
E.g [End, (Prl s Bar ss)] -> [End, s, ss]
E.g [End, End Bar End] -> [End, End, End]
This is how I thought of implementing it,
sepTimes :: [LocalType] -> [LocalType]
sepTimes(x:[]) = [x]
sepTimes(x:xs)
| x == End = sepTimes (x:xs)
| x == (Prl s Bar ss) = do
sepTimes (s:xs)
sepTimes (ss:xs)
As the error messages states, I am unable to retrive the elements s and ss corresponding to End and End in the example of Prl (End Bar End).
app\Sequents.hs:44:17: error: Variable not in scope: s :: LocalType
|
44 | | x == (Prl s Bar ss) = do
| ^
app\Sequents.hs:44:23: error:
* Variable not in scope: ss :: LocalType
* Perhaps you meant `xs' (line 42)
|
44 | | x == (Prl s Bar ss) = do
| ^^
app\Sequents.hs:45:19: error: Variable not in scope: s :: LocalType
|
45 | sepTimes (s:xs)
| ^
app\Sequents.hs:46:19: error:
* Variable not in scope: ss :: LocalType
* Perhaps you meant `xs' (line 42)
|
46 | sepTimes (ss:xs)
| ^^
Here are the defined datatypes :
data Seperator = Bar | BackAmpersand
deriving (Show, Eq, Ord, Read)
data LocalType = End
| Prl LocalType Seperator LocalType
deriving (Eq, Ord, Read)
You're confusing equality checks with pattern matching. Intuitively, all of the following should be the same:
f :: Either Int Char -> String
f (Left i) = show i
f (Right c) = [c]
f :: Either Int Char -> String
f x = case x of
Left i -> show i
Right c -> [c]
f :: Either Int Char -> String
f x
| x==Left i = show i -- what?
| x==Right c = [c]
But actually, only the first two are equivalent, the last one doesn't work. Why? You can't match a variable out of an equality statement. That may work in some logical languages where the equality is propositional, but Haskell's == operator is simply boolean: it takes two fully known values and tells you whether or not they're exactly the same. I.e., in order to be able to write x==Left i, the variable i must already be defined.

How to use same tree after use it in same function in Haskell Recursive Function

data HuffmanTree
= Empty
| Intermediate Integer HuffmanTree HuffmanTree
| Leaf Char Integer
deriving (Show,Eq)
decode :: HuffmanTree -> [Char] -> [Char]
decode (Intermediate n x y) (z:zs) =
if ..... (some checks for x,y,z).....
then [getChar x] ++ (decode (Intermediate n x y) zs)
in this function I m moving on a tree. At "then" part I take deepest Leaf's x and after "++" I should give whole input tree again.The problem is : After ++ part still my function accepts my current tree (deepest leaf's parent). How to fix it ? (I can't change the type of decode, because it is predefined at homework)
You could pass the original tree along as an additional parameter:
decode' :: HuffmanTree -> HuffmanTree -> [Char] -> [Char]
decode' (Intermediate originalN originalX originalY) (Intermediate n x y) (z:zs) =
if ..... (some checks for x,y,z).....
then [getChar x] ++ (decode' (Intermediate originalN originalX originalY) (Intermediate originalN originalX originalY) zs)
so that you have access to the whole input tree at any point.

Concatenating strings together into a list

What I'm trying to do is that I want to take a list of strings as input and do some operations then return back a list of strings. The problem is, I am looking for specific yet generic patterns of the string for each case:
func :: [String] -> [String]
func [] = []
func [x] = [x]
func (["Not","(","Not"]:es:[")"]) = es --HERE
func ("Not":"(":pred:"And":rest:")") = ("Not":pred:"Or":(pushNotInwards rest))
func ("Not":"(":pred:"Or":rest:")") = ("Not":pred:"And":(pushNotInwards rest))
func ("Not":"(":"ForAll":x:scope:")") = ("Exists":"Not":"("scope:")")
func ("Not":"(":"Exists":x:scope:")") = ("ForAll":"Not":"(":scope:")")
For the third case for instance, I want to take a list of strings in the form of:
["Not","(","Not",some_strings,")"]
I tried using ++ on the left hand side as:
func (["Not"]++["("]++["Not"])++es++[")"]) = es
I also tried concat and : but they didn't work either. Any suggestions?
You seem to have some confusion about the different string operators.
A String is just a synonym for a list of chars i.e. [Char]. The colon : operator (aka cons) adds one element to the beginning of a list. Here's its type:
*Main> :t (:)
(:) :: a -> [a] -> [a]
For example:
*Main> 1:[2,3]
[1,2,3]
*Main> 'a':"bc"
"abc"
The ++ operator concatenates two lists. Here's its type:
*Main> :t (++)
(++) :: [a] -> [a] -> [a]
Pattern matching can only be done using a data constructor. The : operator is a data constructor, but the ++ operator is not. So you cannot define a function using pattern matching over the ++ operator.
To define a function using pattern matching, I'd suggest defining a new data type for the different functions and qualifier rather than using strings:
-- Logic Operation
data LogicOp =
Not LogicOp | And [LogicOp] | Or [LogicOp] |
Forall String LogicOp | Exists String LogicOp | T | F
deriving (Eq, Show)
func :: LogicOp -> LogicOp
func (Not (Not x)) = x
func (Not (And (pred:rest))) = Or (Not pred:[func (Not (And rest))])
func (Not (Or (pred:rest))) = And (Not pred:[func (Not (Or rest))])
func (Not (Forall x scope)) = Exists x (Not scope)
func (Not (Exists x scope)) = Forall x (Not scope)
func x = x
Here are some examples:
*Main> func (Not (Not T))
T
*Main> func (Not (And [T, F, T]))
Or [Not T,Or [Not F,Or [Not T,Not (And [])]]]
*Main> func (Not (Or [T, F, T]))
And [Not T,And [Not F,And [Not T,Not (Or [])]]]
*Main> func (Not (Forall "x" (And T F))
*Main> func (Not (Forall "x" (And [T, F])))
Exists "x" (Not (And [T,F]))
*Main> func (Not (Exists "x" (And [T, F])))
Forall "x" (Not (And [T,F]))
You should probably not use strings for that. Create a new type:
data SomeExpr = Not SomeExpr
| And SomeExpr SomeExpr
| Or SomeExpr SomeExpr
deriving (Show)
Then you could match on that expression:
func :: SomeExpr -> SomeExpr
func (Not (Not x)) = func x
func (Not (And x y)) = Or (Not $ func x) (Not $ func y)
func (Not (Or x y)) = And (Not $ func x) (Not $ func y)
...
func x = x
You can't pattern match a list in the middle, e.g You want to match [1,2,3,4,5] with (1:middle:5:[]), but this is invalid.
Yes, using an own type has it's own problems, you have to parse it etc, but it is much more easier and safer than with strings (which could have arbitrary content).

Haskell, creating a binary search tree from a list

Can someone tell me why this code isn't producing what I want.
data BST = MakeNode BST String BST
| Empty
add :: String -> BST -> BST
add new Empty = (MakeNode Empty new Empty)
add string tree#(MakeNode left value right)
| string > value = MakeNode left value (add string right)
| string < value = MakeNode (add string left) value right
| otherwise = tree
output
"John"
"Doug"
"Charlie"
"Alice"
listToBST :: [String] -> BST
listToBST = foldr add Empty
If we create and function which takes a BST and returns a list in sorted order, modelled after sort . nub, then your Tree is fine as quickcheck tells us. QuickCheck is very easy to use.
import Data.List
import Test.QuickCheck
data BST = MakeNode BST String BST
| Empty
deriving (Show)
add :: String -> BST -> BST
add new Empty = (MakeNode Empty new Empty)
add string tree#(MakeNode left value right)
| string > value = MakeNode left value (add string right)
| string < value = MakeNode (add string left) value right
| otherwise = tree
test = ["alice", "blup", "test", "aa"]
manual_test = inorder (foldr add Empty test) == sort (nub test)
prop_inorder = property inorder_test
where inorder_test :: [String] -> Bool
inorder_test xs = inorder (foldr add Empty xs) == sort (nub xs)
-- return sorted nodes
inorder :: BST -> [String]
inorder (Empty) = []
inorder (MakeNode l x r) = inorder l ++ (x : inorder r)
Just load ghci and then run quickCheck prop_inorder.
Other useful functions are:
reverseOrder :: BST -> [String]
reverseOrder Empty = []
reverseOrder (MakeNode l x r) = reverseOrder r ++ (x : reverseOrder r)
asList :: BST -> [String]
asList Empty = []
asList (MakeNode l x r) = x : (asList l ++ asList r)
And also think about making your tree more general by parameterizing over a:
data BST a = Empty | MakeNode (BST a) a (BST a)
You can make it than an instance of Functor, Monad, Foldable and all kind of handy typeclasses.
I tried it and it seems ok to me. It could help if you gave an example of an input that it doesn't work for.
I think the problem may be that string comparison does not work the way you expect ("123" < "7" because "1" < "7"). If I'm right, you might want to use Ints instead of Strings or even better, the class Ord of all the types that can be ordered using (<).

Resources