, которое фокусируется на файле с заданным именем. Этот файл должен присутствовать в текущем каталоге, находящемся в фокусе. Данная функция не производит поиск везде – она просто смотрит в текущем каталоге.
Сначала мы используем функцию >break
, чтобы разбить список элементов в каталоге на те, что предшествуют искомому нами файлу, и те, что идут за ним. Функция >break
принимает предикат и список и возвращает пару списков. Первый список в паре содержит элементы, для которых предикат возвращает значение >False
. Затем, когда предикат возвращает значение >True
для элемента, функция помещает этот элемент и остальную часть списка во второй элемент пары. Мы создали вспомогательную функцию >nameIs
, которая принимает имя и элемент файловой системы и, если имена совпадают, возвращает значение >True
.
Теперь >ls
– список, содержащий элементы, предшествующие искомому нами элементу; >item
является этим самым элементом, а >rs
– это список элементов, идущих за ним в его каталоге. И вот сейчас, когда они у нас есть, мы просто представляем элемент, полученный нами из функции >break
, как фокус и строим «хлебную крошку», которая содержит все необходимые ей данные.
Обратите внимание, что если имя, которое мы ищем, не присутствует в каталоге, образец >item:rs
попытается произвести сопоставление с пустым списком, и мы получим ошибку. А если наш текущий фокус – файл, а не каталог, мы тоже получим ошибку, и программа завершится аварийно.
Итак, мы можем двигаться вверх и вниз по нашей файловой системе. Давайте начнём движение с корня и перейдём к файлу >"skull_man(scary).bmp"
:
>ghci> let newFocus = (myDisk, []) -: fsTo "pics" -: fsTo "skull_man(scary).bmp"
Значение >newFocus
теперь – застёжка, сфокусированная на файле >skull_man(scary).bmp
. Давайте получим первый компонент застёжки (сам фокус) и посмотрим, так ли это на самом деле.
>ghci> fst newFocus
>File "skull_man(scary).bmp" "Ой!"
Переместимся выше и сфокусируемся на соседнем с ним файле >"watermelon_smash.gif"
:
>ghci> let newFocus2 = newFocus –: fsUp –: fsTo "watermelon_smash.gif"
>ghci> fst newFocus2
>File "watermelon_smash.gif" "шмяк!!"
Манипулируем файловой системой
Теперь, когда мы можем передвигаться по нашей файловой системе, ею легко манипулировать. Вот функция, которая переименовывает находящийся в данный момент в фокусе файл или каталог:
>fsRename :: Name –> FSZipper –> FSZipper
>fsRename newName (Folder name items, bs) = (Folder newName items, bs)
>fsRename newName (File name dat, bs) = (File newName dat, bs)
Давайте переименуем наш каталог >"pics"
в >"cspi"
:
>ghci> let newFocus = (myDisk, []) –: fsTo "pics" –: fsRename "cspi" –: fsUp