Как я могу вернуть значение Maybe из нотации do в PureScript?

Я пытаюсь вернуть значение Maybe из функции, использующей нотацию do, но мне не удается заставить ее работать. Эта функция принимает строку ("имя файла") и путь для поиска в ...

findIn :: String -> Path -> Maybe Path
findIn search start = do
    file <- ls start
    if ((filename file) == search)
      then Just file
      else Nothing

Где...

ls :: Path -> Array Path
filename :: Path -> String

Но я продолжаю получать ошибку «Count not match Type Array with type Maybe», поэтому похоже, что компилятор ожидает, что нотация do вернет массив. Как мне вернуть значение может быть?


person Albtzrly    schedule 03.04.2016    source источник


Ответы (2)


Вы не можете так смешивать монады.

Когда вы пишете:

file <- ls start

это немного похоже на выражение «для каждого значения file в массиве ...», так что вы находитесь в контексте нескольких возможных значений.

Но тогда остальная часть кода находится в контексте Maybe, который может обрабатывать только одно (или ноль) значения.

В модуле Data.Foldable есть функция find, которая выполняет основную часть работы вашей основной функции путем поиска одного элемента, который соответствует некоторым критериям. Его фактический тип является более общим, но когда он ограничен массивами, он выглядит следующим образом:

find :: forall a. (a -> Boolean) -> Array a -> Maybe a

Тогда вы можете просто написать:

findIn search start = find (\x => x == search) $ ls start
person Peter Hall    schedule 03.04.2016
comment
Хорошо, я думаю, что понимаю. Итак, нотация должна возвращать массив, и все выражения предназначены для фильтрации и сопоставления этих массивов. - person Albtzrly; 03.04.2016
comment
Да это правильно. Если вы хотите вернуть Maybe, тогда блок do должен быть полностью о Maybe. Я немного обновил свой ответ. - person Peter Hall; 03.04.2016
comment
Спасибо, что разъяснили это. Это замечание о нахождении в контексте «Может быть» и в контексте множества возможных значений имеет смысл. Раньше я об этом не думал. - person Albtzrly; 03.04.2016

Хорошо, я нашел кое-что, что работает, но я не уверен, что это идеально.

findIn :: String -> Path -> Maybe Path
findIn search start = if (length r == 1)
                      then head r
                      else Nothing
  where
    r = do
      file <- ls start
      guard $ (filename file) == search
      [file]

Похоже, что do-notation возвращает значение типа Array (Maybe Path).

person Albtzrly    schedule 03.04.2016