1. Trees in F# Defining a type of trees Creating trees Function that take trees as input or produce trees as output Trees are recursive datatypes, used for • hierarchies , • directory structure , • document object model (DOM) in browsers, • syntax of programs, • efficient datatypes , • and more. In F#, trees can be defined using a custom data type that represents a node in the tree. A tree can be thought of as a collection of nodes, where each node has a value and may have one or more child nodes. Defining a type of trees: To define a type of trees in F#, you can use a discriminated union. For example, the following code defines a binary tree: type 'a tree = | LEAF | NODE of 'a * 'a tree * 'a tree A tree (of αs) is either • a leaf (an empty tree), or • a node that contains an α and a left and a right branch, both trees (of αs). This code defines a type called 'a tree, where 'a represents the type of values stored in the tree. The tree can have two possible forms: 1. LEAF represents an empty tree or a leaf node with no children. 2. NODE represents a non-empty tree with a value of type 'a and two subtrees of type 'a tree. let tree1 = LEAF // Creates an empty tree (leaf node) let tree2 = NODE(5, LEAF, LEAF) // Creates a tree with a single node containing the value 5 let tree3 = NODE(10, NODE(7, LEAF, LEAF), NODE(15, LEAF, LEAF)) // Creates a tree with three levels In the above examples, tree1 represents an empty tree (a leaf node), tree2 represents a tree with a single node containing the value 5, and tree3 represents a tree with three levels. Each level contains a node with a value and two leaf nodes. Functions: let rec treeSum (tree: 'a tree) : int = match tree with | LEAF -> 0 | NODE(value, left, right) -> value + treeSum left + treeSum right The treeSum function takes a tree and calculates the sum of all the values in the tree. It uses pattern matching to handle the two possible cases: if the tree is a leaf, the sum is 0, and if the tree is a node, it recursively sums the value of the current node with the sums of the left and right subtrees. let rec treeDepth (tree: 'a tree) : int = match tree with | LEAF -> 0 | NODE(_, left, right) -> 1 + max (treeDepth left) (treeDepth right) The treeDepth function takes a tree and recursively calculates its depth. It uses pattern matching to handle the two cases: if the tree is a leaf, the depth is 0. If the tree is a node, it recursively calculates the depths of the left and right subtrees and adds 1 to the maximum depth among them. let rec treeMap (f: 'a -> 'b) (tree: 'a tree) : 'b tree = match tree with | LEAF -> LEAF | NODE(value, left, right) -> NODE(f value, treeMap f left, treeMap f right)