Haskell defining a tree - haskell

In haskell I can do things such as
a :: Int
a = 15
I have the datatype as below
data Btree a = ND | Data a | Branch (Btree a) (Btree a) deriving (Show, Eq)
How can I define a tree, not using a function, such as above.
I have tried;
tree :: BTree
tree = Branch Btree (Branch ND Data 1) (Branch ND (Branch ND ND))
I cannot seem to get it to work (I am new to haskell so if this is very basic I apologise in advance)

Keep in mind that to construct an instance of the data type you need to call one of its constructor functions. All these constructors, ND, Data, Branch, are just regular functions, so you should call them as such.
In your tree, you are mixing data types (Btree) with constructors, while you should only be using constructors. Also, keep in mind that the function call (the 'space operator' is left-associated) is very greedy, so Branch ND Data 1 calls the function Branch with 3 arguments, rather than what you want: Branch ND (Data 1).
So to create your tree of depth 2 considering the above you write:
tree = Branch (Branch ND (Data 1)) (Branch ND (Branch ND ND))

Note that Data 1 will be a Btree as well without any additional baggage
Prelude> :t (Data 1)
(Data 1) :: Num a => Btree a
if you want a simple branch with a right element only you can write
Branch ND (Data 1)
or two level deep as in the other answer. At this point convenient constructor functions will be handy to minimize noise and typing.

Related

Accessing values in haskell custom data type

I'm very new to haskell and need to use a specific data type for a problem I am working on.
data Tree a = Leaf a | Node [Tree a]
deriving (Show, Eq)
So when I make an instance of this e.g Node[Leaf 1, Leaf2, Leaf 3] how do I access these? It won't let me use head or tail or indexing with !! .
You perform pattern matching. For example if you want the first child, you can use:
firstChild :: Tree a -> Maybe (Tree a)
firstChild (Node (h:_)) = Just h
firstChild _ = Nothing
Here we wrap the answer in a Maybe type, since it is possible that we process a Leaf x or a Node [], such that there is no first child.
Or we can for instance obtain the i-th item with:
iThChild :: Int -> Tree a -> Tree a
iThChild i (Node cs) = cs !! i
So here we unwrap the Node constructor, obtain the list of children cs, and then perform cs !! i to obtain the i-th child. Note however that (!!) :: [a] -> Int -> a is usually a bit of an anti-pattern: it is unsafe, since we have no guarantees that the list contains enough elements, and using length is an anti-pattern as well, since the list can have infinite length, so we can no do such bound check.
Usually if one writes algorithms in Haskell, one tends to make use of linear access, and write total functions: functions that always return something.

Generate n-ary binary tree in haskell

I try to create random trees from this structure:
data Tree a = Leaf a
| Funktion (Tree a) (Tree a)
| Lambda (Tree a)
deriving (Show)
The problem I have is that I don't even know how to generate a tree with the depth of (for example) 2 which only has "Lambda" as nodes. If someone could help me with generating this simple tree (depth 2) I could generate them randomly.
If I implement a function like this:
build (Tree a) 0 = Leaf "A"
build (Tree a) n = build (Lambda a) (n-1)
It won't work since the function build itself expects a Tree as input. Actually I need trees which have the nodes Lambda or Funktion, but first of all I need to understand how to generate a simple version of this structure.
It sounds like you want something like
build :: Natural -- ^ Number, n, of Lambda nodes
-> a -- ^ Value, v, to store in the Leaf
-> Tree a -- ^ Lambda^n (Leaf v)
build 0 a = Leaf a
build n a = Lambda (build (n - 1) a)
So that build 4 "A" will produce
Lambda (Lambda (Lambda (Lambda (Leaf "A"))))
Unfortunately, the rest of your question (about generating random trees) really requires substantially more context to answer.
You're close - your build function at the moment will always return a Leaf, as the base case of the recursion doesn't do anything with its argument. You don't actually need the argument:
build :: Integer -> Tree String
build 0 = Leaf "A"
build n = Lambda $ build (n-1)
This would produce what your build function seems to be intending, that is a simple "tree" of given depth n composed of a Leaf node and Lambda nodes. Eg:
λ> build 2
Lambda (Lambda (Leaf "A"))
To get your randomly generated tree, you need to look at the System.Random module.
For example building on the previous, a tree of random height between a given upper and lower bound:
buildRandom :: (Integer, Integer) -> IO (Tree String)
buildRandom bounds = randomRIO bounds >>= return . build
This can be extended and modified to produce the behaviour you want (a fully random generated tree), but requires knowledge of monads etc., which might take some extra reading.

Data type for Tree in Haskell

For a data type of a binary tree you can write something like this:
data Tree a = Nil | Node a (Tree a) (Tree a)
So if I do want to include trees, with Nodes having more than just two children, how could the data type possibly look like?
A lesser known technique is Left-child right-sibling where you can use the exact same type to encode trees with more than two children per node:
data Tree a
= Nil
| Node a (Tree a) (Tree a) -- value, left child, right sibling
The alternative [Tree a] does not have a performance advantage, since Haskell lists are linked lists.
You can either have a fixed branching factor:
data BinaryTree a = BTNil
| BTNode a (BinaryTree a) (BinaryTree a)
data TernaryTree a = TTNil
| TTNode a (TernaryTree a) (TernaryTree a) (TernaryTree a)
data QuadTree a = QTNil
| QTNode a (QuadTree a) (QuadTree a) (QuadTree a) (QuadTree a)
-- etc
(Note that QuadTree isn't a great name for a general tree with a branching factor of 4, since there is a specific data structure with that name.)
or you can simply use a rose tree, which stores an arbitrary list of children at each node.
data RoseTree a = RTNil | RTNode a [RoseTree a]
There is some duplication here, as RTNil is only needed to store an explicit empty tree. Leaf nodes are just RTNode a []. (Consider what difference, if any, you would assign to the values RTNode 3 [], RTNode 3 [RTNil], RTNode 3 [RTNil, RTNil], etc.)

Haskell: Implementation of a Complete Binary-Leaf Tree

I'm attempting to generate a complete binary-leaf tree using Haskell.
However, I'm not sure whether I am along the right lines.
I have the following code at the moment (not sure if it's right):
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Show,Eq)
listToTree :: [a] -> Tree a
listToTree [] = error "The list cannot be empty"
listToTree [x] = Leaf x
I need the function to take in an input list of any basic types and construct a tree using level first order from the list provided as input. I'm not sure what the best way to do this is.
Any suggestions?

Converting rose trees to different binary tree types

I am completely lost on how to do some tree conversions in Haskell. I need to go from a rose tree defined as:
data Rose a = Node a [Rose a] deriving (Eq, Show, Ord)
to a binary tree which is defined as:
data Btree a = Empty | Fork a (Btree a) (Btree a) deriving (Eq, Show, Ord)
In my class I was given a function that is similar, but using a different definition of the binary tree. For that function the rose tree is defined the same and the binary tree is defined as:
Btree a = Leaf a | Fork (Btree a) (Btree a)
with the function from rose tree to binary tree defined as:
toB :: Rose a -> Btree a
toB (Node x xts) = foldl Fork (Leaf x) (map toB xts)
toB (Node x []) = foldl Fork (Leaf x) []
I have the answer but I don't know how to convert it so that it works with the new definition of Btree.
When I did something like this, I considered the "left" subtree to be the first child, and the "right" subtree to be the siblings of the node. This means that you convert the tree like so:
h h
/|\ /
/ | \ /
b d e ==> b->d->e
/ \ / \ / /
a c f g a->c f->g
h is still the root, but in the second diagram / is the left subtree and -> is the right. Leaves have no left subtree, but might have siblings (right subtrees). The root has no right subtree, but might have children (left subtree). Internal nodes have both.
Does that help?
Try to write a function converting from the first to the second definition of the binary tree. Then convB . toB is your new function! Now, systematically create a new function that acts directly as a fusion of the two, by inlining one into the other, and you'll get a straightforward and elegant solution.

Resources