===== 10. Trees ===== File systems are one common application that uses a tree representation. We define the following data type to model a very simplistic file system: data FTree = Dir String [FTree] | File String deriving (Show, Eq) The ''deriving (Show, Eq)'' at the end offer a default enrollment into the ''Show'' and ''Eq'' type classes, which allows us to represent our filesystem as a string using ''show'' and to compare two filesystems using ''=='' and ''/=''. Each node is a filesystem entry; directory nodes have a name and a list of children (its contents: other directories or files) and regular files are leaves (no children) characterized by their name. Here is an example filesystem instance: t = Dir "/" [Dir "usr" [Dir "share" [], Dir "var" [], Dir "include" [File "stdio.h", File "string.h", File "stdlib.h"]], Dir "dev" [File "sda", File "sda1", File "sda2"], Dir "etc" [File "sudoers", File "passwd", File "shadow"], Dir "home" [Dir "mihai" [File ".zshrc", Dir "sol" [File "Lab10.hs"]], Dir "student" [File ".bashrc", Dir "sol" []]]] We also define a ''Path'' to be a list of names, representing a way through the tree, from the root to a particular node. type Path = [String] path1 = ["/", "usr", "include", "stdio.h"] path2 = ["/", "home", "student"] wrongPath1 = ["/", "usr", "include", "math.h"] wrongPath2 = ["/", "sbin"] 10.1 Write a function ''countFiles :: FTree -> Int'' that counts how many regular files are there in a filesystem. 10.2 Write a function ''longestPath :: FTree -> Int'' which gives the length of the longest path in the filesystem. 10.3 Write a function ''findEntry :: String -> FTree -> Bool'' which takes the name of an entry (dir or file) and a filesystem and determines whether that entry can be found in the filesystem. 10.4 Write a function ''checkExists :: Path -> FTree -> Bool'' which takes a path and a filesystem and determines whether there exists an entry with that path. 10.5 Write a function ''checkIsFile :: Path -> FTree -> Bool'' which takes a path and a filesystem and determines whether there exists a **regular file** with that path (if the path exists, but it's a dir, the result should be ''False''). 10.6 Write a function ''checkIsDir :: Path -> FTree -> Bool'' which takes a path and a filesystem and determines whether there exists a **directory** with that path (if the path exists, but it's a regular file, the result should be ''False''). 10.7 Write a function ''touch :: Path -> FTree -> FTree'' which takes a path and a filesystem and produces a new filesystem. If the path existed in the original, nothing changes. If the path didn't exist in the original, the new filesystem will contain a regular file at that path. 10.8 Write a function ''mkdir :: Path -> FTree -> FTree'' which takes a path and a filesystem and produces a new filesystem. If the path existed in the original, nothing changes. If the path didn't exist in the original, the new filesystem will contain a directory at that path. 10.9 Write a function ''rm :: Path -> FTree -> FTree'' which takes a path and a filesystem and produces a new filesystem without the entry at that path. 10.10 Write a function ''longestPath2 :: FTree -> Path'' which takes a filesystem and returns the longest path. 10.11 Write a function ''findEntry2 :: String -> FTree -> Path'' which takes the name of an entry (dir or file) and a filesystem and determines whether that entry can be found in the filesystem. If it doesn't exist, an empty path ''[]'' is returned.