Functional Data Structures

Tessa Kelly

engineer at NoRedInk

@t_kelly9

Binary Tree API

module BinaryTree
    exposing
        ( BinaryTree
        , new
        , empty
        , member
        , insert
        , remove
        )

Array
Dict
Tree I & II

Array Based

Strategy:

  • Use Array as our base
  • Derive child indices
  • Hope for a complete binary tree
type alias BinaryTree comparable =
    Array (Maybe comparable)


leftChild : Int -> Int
leftChild index =
    2 * index + 1


rightChild : Int -> Int
rightChild index =
    2 * index + 2


empty : BinaryTree comparable
empty =
    Array.empty


new : comparable -> BinaryTree comparable
new value =
    Array.initialize 1 (\_ -> Just value)


member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Just Nothing ->
            Array.set index (Just value) tree

        Nothing ->
            fillWithEmptiesUntil index value tree


fillWithEmptiesUntil : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
fillWithEmptiesUntil index value tree =
    Array.repeat (index - Array.length tree) Nothing
        |> Array.push (Just value)
        |> Array.append tree


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Array.get (leftChild index) tree, Array.get (rightChild index) tree ) of
                    ( Just (Just leftValue), _ ) ->
                        Array.set index (Just leftValue) (removeAt (leftChild index) leftValue tree)

                    ( _, Just (Just rightValue) ) ->
                        Array.set index (Just rightValue) (removeAt (rightChild index) rightValue tree)

                    ( _, _ ) ->
                        Array.set index Nothing tree

        _ ->
            tree

Shape of a Node

type alias BinaryTree comparable =
    Array (Maybe comparable)

Creating a Binary Tree

type alias BinaryTree comparable =
    Array (Maybe comparable)


empty : BinaryTree comparable
empty =
    Array.empty


new : comparable -> BinaryTree comparable
new value =
    Array.initialize 1 (\_ -> Just value)

Checking for Values

member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False

Inserting Values

insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Just Nothing ->
            Array.set index (Just value) tree

        Nothing ->
            .... uh oh!!!
insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Just Nothing ->
            Array.set index (Just value) tree

        Nothing ->
            fillWithEmptiesUntil index value tree


fillWithEmptiesUntil : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
fillWithEmptiesUntil index value tree =
    Array.repeat (index - Array.length tree) Nothing
        |> Array.push (Just value)
        |> Array.append tree
remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Array.get index tree of
        Just (Just nodeValue) ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Array.get (leftChild index) tree, Array.get (rightChild index) tree ) of
                    ( Just (Just leftValue), _ ) ->
                        Array.set index (Just leftValue) (removeAt (leftChild index) leftValue tree)

                    ( _, Just (Just rightValue) ) ->
                        Array.set index (Just rightValue) (removeAt (rightChild index) rightValue tree)

                    ( _, _ ) ->
                        Array.set index Nothing tree

        _ ->
            tree

Removing Values

Eek!
Types, halp!
 

Adding a Node type

This helps make our code more readable by cutting out the bananas `Just Nothing` business, but it doesn't solve all of our problems with this implementation.

type alias BinaryTree comparable =
    Array (Node comparable)


type Node comparable
    = Node comparable
    | Empty


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Array.get index tree of
        Just (Node nodeValue) ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Just Empty ->
            Array.set index (Node value) tree

        Nothing ->
            fillWithEmptiesUntil index value tree


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Array.get index tree of
        Just (Node nodeValue) ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Array.get (leftChild index) tree, Array.get (rightChild index) tree ) of
                    ( Just (Node leftValue), _ ) ->
                        Array.set index (Node leftValue) (removeAt (leftChild index) leftValue tree)

                    ( _, Just (Node rightValue) ) ->
                        Array.set index (Node rightValue) (removeAt (rightChild index) rightValue tree)

                    ( _, _ ) ->
                        Array.set index Empty tree

        _ ->
            tree

Dict Based

Strategy:

  • Use Dict as our base
  • Derive child indices
  • Continue using helpers to our advantage
     
type alias BinaryTree comparable =
    Dict Int comparable


empty : BinaryTree comparable
empty =
    Dict.empty


member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Nothing ->
            Dict.insert index value tree


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Dict.get (leftChild index) tree, Dict.get (rightChild index) tree ) of
                    ( Just leftValue, _ ) ->
                        Dict.insert index leftValue (removeAt (leftChild index) leftValue tree)

                    ( _, Just rightValue ) ->
                        Dict.insert index rightValue (removeAt (rightChild index) rightValue tree)

                    ( Nothing, Nothing ) ->
                        Dict.remove index tree

        _ ->
            tree


leftChild : Int -> Int
leftChild index =
    2 * index + 1


rightChild : Int -> Int
rightChild index =
    2 * index + 2


new : comparable -> BinaryTree comparable
new value =
    Dict.singleton 0 value

Creating a Binary Tree

type alias BinaryTree comparable =
    Dict Int comparable


empty : BinaryTree comparable
empty =
    Dict.empty


new : comparable -> BinaryTree comparable
new value =
    Dict.singleton 0 value


member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0

Checking for Values

member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False

Inserting Values

insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Nothing ->
            Dict.insert index value tree

Removing Values

remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Dict.get (leftChild index) tree, Dict.get (rightChild index) tree ) of
                    ( Just leftValue, _ ) ->
                        Dict.insert index leftValue (removeAt (leftChild index) leftValue tree)

                    ( _, Just rightValue ) ->
                        Dict.insert index rightValue (removeAt (rightChild index) rightValue tree)

                    ( Nothing, Nothing ) ->
                        Dict.remove index tree

        _ ->
            tree

Tree Based, I

Strategy:

  • Use "pointers"
  • Pretend records have entirely analogous uses to JavaScript Objects
  • Hope that the types stay nice
type BinaryTree comparable
    = Node
        { value : comparable
        , left : BinaryTree comparable
        , right : BinaryTree comparable
        }
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node
        { value = value
        , left = Empty
        , right = Empty
        }


member : comparable -> BinaryTree comparable -> Bool
member value tree =
    case tree of
        Node node ->
            if value < node.value then
                member value node.left
            else if value > node.value then
                member value node.right
            else
                value == node.value

        Empty ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = insert value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = insert value node.right
                    }
            else
                Node node

        Empty ->
            new value


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = remove value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = remove value node.right
                    }
            else
                case ( node.left, node.right ) of
                    -- No children to consider
                    ( Empty, Empty ) ->
                        empty

                    -- One child, on the right
                    ( Empty, Node rightTree ) ->
                        Node rightTree

                    -- One child, on the left
                    ( Node leftTree, Empty ) ->
                        Node leftTree

                    -- Two children, right and left
                    ( Node leftTree, Node rightTree ) ->
                        Node
                            { value = rightTree.value
                            , left = Node leftTree
                            , right = remove rightTree.value (Node rightTree)
                            }

        Empty ->
            Empty
type BinaryTree comparable
    = Node
        { value : comparable
        , left : BinaryTree comparable
        , right : BinaryTree comparable
        }
    | Empty

Shape of a Node

type BinaryTree comparable
    = Node
        { value : comparable
        , left : BinaryTree comparable
        , right : BinaryTree comparable
        }
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node
        { value = value
        , left = Empty
        , right = Empty
        }

Creating a Binary Tree

insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = insert value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = insert value node.right
                    }
            else
                Node node

        Empty ->
            new value

Inserting Values

remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = remove value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = remove value node.right
                    }
            else
                case ( node.left, node.right ) of
                    ( Empty, Empty ) ->
                        empty

                    ( Empty, Node rightTree ) ->
                        Node rightTree

                    ( Node leftTree, Empty ) ->
                        Node leftTree

                    ( Node leftTree, Node rightTree ) ->
                        Node
                            { value = rightTree.value
                            , left = Node leftTree
                            , right = remove rightTree.value (Node rightTree)
                            }

        Empty ->
            Empty

Tree Based, II

Strategy:

  • Create types to describe the shape of a node
  • Use casing to our advantage
type BinaryTree comparable
    = Node comparable (BinaryTree comparable) (BinaryTree comparable)
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node value empty empty


member : comparable -> BinaryTree comparable -> Bool
member value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                member value left
            else if value > nodeValue then
                member value right
            else
                value == nodeValue

        Empty ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (insert value left) right
            else if value > nodeValue then
                Node nodeValue left (insert value right)
            else
                Node nodeValue left right

        Empty ->
            new value


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (remove value left) right
            else if value > nodeValue then
                Node nodeValue left (remove value left)
            else
                case ( left, right ) of
                    ( Empty, Empty ) ->
                        empty

                    ( Empty, (Node _ _ _) as rightChild ) ->
                        rightChild

                    ( (Node _ _ _) as leftChild, Empty ) ->
                        leftChild

                    ( Node _ _ _, (Node rightChildValue _ _) as rightChild ) ->
                        Node rightChildValue left (remove value rightChild)

        Empty ->
            Empty

Shape of a Node


type BinaryTree comparable
    = Node comparable (BinaryTree comparable) (BinaryTree comparable)
    | Empty

Creating a Binary Tree

type BinaryTree comparable
    = Node comparable (BinaryTree comparable) (BinaryTree comparable)
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node value empty empty

Inserting Values

insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (insert value left) right
            else if value > nodeValue then
                Node nodeValue left (insert value right)
            else
                Node nodeValue left right

        Empty ->
            new value

Checking for Values

member : comparable -> BinaryTree comparable -> Bool
member value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                member value left
            else if value > nodeValue then
                member value right
            else
                value == nodeValue

        Empty ->
            False
remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (remove value left) right
            else if value > nodeValue then
                Node nodeValue left (remove value left)
            else
                case ( left, right ) of
                    ( Empty, Empty ) ->
                        empty

                    ( Empty, (Node _ _ _) as rightChild ) ->
                        rightChild

                    ( (Node _ _ _) as leftChild, Empty ) ->
                        leftChild

                    ( Node _ _ _, (Node rightChildValue _ _) as rightChild ) ->
                        Node rightChildValue left (remove value rightChild)

        Empty ->
            Empty

Removing Values

Thanks!

Enjoy the rest of the conference!

@t_kelly9

type alias BinaryTree comparable =
    Array (Node comparable)


type Node comparable
    = Node comparable
    | Empty


empty : BinaryTree comparable
empty =
    Array.empty


new : comparable -> BinaryTree comparable
new value =
    Array.initialize 1 (\_ -> Node value)


member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Array.get index tree of
        Just (Node nodeValue) ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Array.get index tree of
        Just (Node nodeValue) ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Just Empty ->
            Array.set index (Node value) tree

        Nothing ->
            fillWithEmptiesUntil index value tree


fillWithEmptiesUntil : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
fillWithEmptiesUntil index value tree =
    Array.repeat (index - Array.length tree) Empty
        |> Array.push (Node value)
        |> Array.append tree


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Array.get index tree of
        Just (Node nodeValue) ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Array.get (leftChild index) tree, Array.get (rightChild index) tree ) of
                    ( Just (Node leftValue), _ ) ->
                        Array.set index (Node leftValue) (removeAt (leftChild index) leftValue tree)

                    ( _, Just (Node rightValue) ) ->
                        Array.set index (Node rightValue) (removeAt (rightChild index) rightValue tree)

                    ( _, _ ) ->
                        Array.set index Empty tree

        _ ->
            tree


leftChild : Int -> Int
leftChild index =
    2 * index + 1


rightChild : Int -> Int
rightChild index =
    2 * index + 2
type alias BinaryTree comparable =
    Dict Int comparable


empty : BinaryTree comparable
empty =
    Dict.empty


new : comparable -> BinaryTree comparable
new value =
    Dict.singleton 0 value


member : comparable -> BinaryTree comparable -> Bool
member =
    memberAt 0


memberAt : Int -> comparable -> BinaryTree comparable -> Bool
memberAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                memberAt (leftChild index) value tree
            else if value > nodeValue then
                memberAt (rightChild index) value tree
            else
                value == nodeValue

        _ ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert =
    insertAt 0


insertAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
insertAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                insertAt (leftChild index) value tree
            else if value > nodeValue then
                insertAt (rightChild index) value tree
            else
                tree

        Nothing ->
            Dict.insert index value tree


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove =
    removeAt 0


removeAt : Int -> comparable -> BinaryTree comparable -> BinaryTree comparable
removeAt index value tree =
    case Dict.get index tree of
        Just nodeValue ->
            if value < nodeValue then
                removeAt (leftChild index) value tree
            else if value > nodeValue then
                removeAt (rightChild index) value tree
            else
                case ( Dict.get (leftChild index) tree, Dict.get (rightChild index) tree ) of
                    ( Just leftValue, _ ) ->
                        Dict.insert index leftValue (removeAt (leftChild index) leftValue tree)

                    ( _, Just rightValue ) ->
                        Dict.insert index rightValue (removeAt (rightChild index) rightValue tree)

                    ( Nothing, Nothing ) ->
                        Dict.remove index tree

        _ ->
            tree


leftChild : Int -> Int
leftChild index =
    2 * index + 1


rightChild : Int -> Int
rightChild index =
    2 * index + 2
type BinaryTree comparable
    = Node
        { value : comparable
        , left : BinaryTree comparable
        , right : BinaryTree comparable
        }
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node
        { value = value
        , left = Empty
        , right = Empty
        }


member : comparable -> BinaryTree comparable -> Bool
member value tree =
    case tree of
        Node node ->
            if value < node.value then
                member value node.left
            else if value > node.value then
                member value node.right
            else
                value == node.value

        Empty ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = insert value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = insert value node.right
                    }
            else
                Node node

        Empty ->
            new value


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node node ->
            if value < node.value then
                Node
                    { value = node.value
                    , left = remove value node.left
                    , right = node.right
                    }
            else if value > node.value then
                Node
                    { value = node.value
                    , left = node.left
                    , right = remove value node.right
                    }
            else
                case ( node.left, node.right ) of
                    ( Empty, Empty ) ->
                        empty

                    ( Empty, Node rightTree ) ->
                        Node rightTree

                    ( Node leftTree, Empty ) ->
                        Node leftTree

                    ( Node leftTree, Node rightTree ) ->
                        Node
                            { value = rightTree.value
                            , left = Node leftTree
                            , right = remove rightTree.value (Node rightTree)
                            }

        Empty ->
            Empty
type BinaryTree comparable
    = Node comparable (BinaryTree comparable) (BinaryTree comparable)
    | Empty


empty : BinaryTree comparable
empty =
    Empty


new : comparable -> BinaryTree comparable
new value =
    Node value empty empty


member : comparable -> BinaryTree comparable -> Bool
member value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                member value left
            else if value > nodeValue then
                member value right
            else
                value == nodeValue

        Empty ->
            False


insert : comparable -> BinaryTree comparable -> BinaryTree comparable
insert value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (insert value left) right
            else if value > nodeValue then
                Node nodeValue left (insert value right)
            else
                Node nodeValue left right

        Empty ->
            new value


remove : comparable -> BinaryTree comparable -> BinaryTree comparable
remove value tree =
    case tree of
        Node nodeValue left right ->
            if value < nodeValue then
                Node nodeValue (remove value left) right
            else if value > nodeValue then
                Node nodeValue left (remove value left)
            else
                case ( left, right ) of
                    ( Empty, Empty ) ->
                        empty

                    ( Empty, (Node _ _ _) as rightChild ) ->
                        rightChild

                    ( (Node _ _ _) as leftChild, Empty ) ->
                        leftChild

                    ( Node _ _ _, (Node rightChildValue _ _) as rightChild ) ->
                        Node rightChildValue left (remove value rightChild)

        Empty ->
            Empty

Thanks!

Enjoy the rest of the conference!

@t_kelly9

Made with Slides.com