Для демонстрации работы застёжек давайте используем деревья, чтобы представить очень простую файловую систему. Затем мы можем создать застёжку для этой файловой системы, которая позволит нам перемещаться между каталогами, как мы это делаем при переходах по реальной файловой системе.
Обычная иерархическая файловая система состоит преимущественно из файлов и каталогов. Файлы – это элементы данных, снабжённые именами. Каталоги используются для организации этих файлов и могут содержать файлы или другие каталоги. Для нашего простого примера достаточно сказать, что элементами файловой системы являются:
• файл под некоторым именем, содержащий некие данные;
• каталог под некоторым именем, содержащий другие элементы, которые сами являются или файлами, или каталогами.
Вот соответствующий тип данных и некоторые синонимы типов, чтобы было понятно, что к чему:
>type Name = String
>type Data = String
>data FSItem = File Name Data | Folder Name [FSItem] deriving (Show)
К файлу прилагаются две строки, представляющие его имя и содержимое. К каталогу прилагаются строка, являющаяся его именем, и список элементов. Если этот список пуст, значит, мы имеем пустой каталог.
Вот каталог с некоторыми файлами и подкаталогами (на самом деле это то, что в настоящую минуту содержится на моём диске):
>myDisk :: FSItem
>myDisk =
> Folder "root"
> [ File "goat_yelling_like_man.wmv" "бааааааа"
> , File "pope_time.avi" "Боже, благослови"
> , Folder "pics"
> [ File "ape_throwing_up.jpg" "блин..."
> , File "watermelon_smash.gif" "шмяк!!"
> , File "skull_man(scary).bmp" "Ой!"
> ]
> , File "dijon_poupon.doc" "лучшая горчица"
> , Folder "programs"
> [ File "sleepwizard.exe" "10 пойти поспать"
> , File "owl_bandit.dmg" "move ax, 42h"
> , File "not_a_virus.exe" "точно не вирус"
> , Folder "source code"
> [ File "best_hs_prog.hs" "main = print (fix error)"
> , File "random.hs" "main = print 4"
> ]
> ]
> ]
Создаём застёжку для нашей файловой системы
Теперь, когда у нас есть файловая система, всё, что нам нужно, – это застёжка, чтобы мы могли застёгивать файловую систему и брать её крупным планом, а также добавлять, изменять и удалять файлы и каталоги. Как и в случае с использованием бинарных деревьев и списков, наши «хлебные крошки» будут содержать информацию обо всём, что мы решили не посещать. Отдельная «хлебная крошка» должна хранить всё, кроме поддерева, на котором мы фокусируемся в данный момент. Она также должна указывать, где находится отверстие, чтобы при перемещении обратно вверх мы смогли вставить в отверстие наш предыдущий фокус.