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)
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.