Haskell - привязка отображенной монадической функции - PullRequest
0 голосов
/ 03 мая 2019

В этом блоке кода у меня есть функция tagsort, которая принимает FilePath и возвращает строку ввода-вывода.

   builddir xs = do
    writeto  <- lastest getArgs
    let folderl b = searchable <$> (getPermissions b)
    let filel   c = ((lastlookup mlookup c) &&) <$> ((not <$> folderl c))
    a <- listDirectory xs
    listdirs <- filterM (folderl) (map ((xs ++ "/") ++) a)
    filedirs <- filterM (filel)   (map ((xs ++ "/") ++) a)
    tagfiles <- tagsort <$> filedirs
--testprint to terminal
    putStrLn $ concat listdirs
    putStrLn $ concat tagfiles


tagsort :: Control.Monad.IO.Class.MonadIO m => FilePath -> m [Char]
tagsort xs = do
    nsartist <- getTags xs artistGetter
    nsalbum  <- getTags xs albumGetter
    let artist = init $ drop 8 $ show nsartist
    let album  = init $ drop 7 $ show nsalbum
    pure (artist ++ " - " ++ album)

Я бы хотел взять эту функцию и отобразить ее в списке каталогов. При запуске я получаю эту ошибку.

• Couldn't match type ‘[]’ with ‘IO’
      Expected type: IO (t0 [Char])
        Actual type: [t0 [Char]]
    • In a stmt of a 'do' block: tagfiles <- tagsort <$> filedirs

Мне кажется, я понимаю, что здесь происходит. Для того, чтобы связать так, как я хочу, чтобы файлы тегов, я хотел бы IO [String], но вместо того, чтобы сопоставить сортировку тегов в списке filedirs, вы получите [IO String]. Я не совсем уверен, как это обойти или можно ли вообще обойти. Возможно, картографирование не является правильным способом сделать это? Любая помощь будет оценена.

1 Ответ

2 голосов
/ 07 мая 2019

Это потому, что функция tagsort имеет тип String -> IO String
Примечание: я использую IO для простоты и String для [Char] и FilePath.

Однако при отображении на filedir :: [String] с использованием

(<$>) = fmap :: Functor f => (a -> b) -> f a -> f b

произошел конфликт между IO [String] и `[IO String] - первый - это то, что компилятор ожидает, что выражение в блоке do будет.

Это не очень полезно на первый взгляд. Однако в haskell есть функция sequence для этой конкретной задачи. Его ограничения не должны иметь большого значения сейчас, поскольку Foldable - это нечто совершенно другое. А пока знайте, что это может быть тип [IO a] -> IO [a]

К счастью, снова есть очень полезная предопределенная служебная функция, mapM только для sequence . map f.

Окончательный код будет:

mapM tagSort fileDirs
...