Haskell Put IO String

Я пытаюсь прочитать и распечатать вывод команды "readProcess", сопоставленной со списком имен файлов:

files <- readProcess "ls" [] []
let mdList = map ( \file -> do
    md <- readProcess "mdls" [file] []
    return md ) $ splitOn "\n" files in
    map (\md -> putStrLn md) mdList
putStrLn "Complete"

Каждый раз, когда я пытаюсь отобразить putStrLn на mdList, я получаю эту ошибку:

Couldn't match type ‘IO String’ with ‘[Char]’

Я прочитал много ответов Stackru, которые, кажется, просто используют putStrLn для строки ввода-вывода, но я не могу это сделать. Кроме того, я новичок в Haskell, поэтому любые другие советы также приветствуются.

1 ответ

Ты используешь

map :: (a -> b) -> [a] -> [b]

который специализируется на

map :: (a -> IO b) -> [a] -> [IO b]

Конечный результат, [IO b] это не то, что нам нужно. Это список IO действия, то есть эквивалент списка невыполненных императивных функций без аргументов. Вместо этого мы хотим один IO действие, результатом которого является список b: это было бы IO [b] вместо [IO b],

Библиотека также обеспечивает это:

mapM :: (a -> IO b) -> [a] -> IO [b]

или, если мы не заботимся о сборе результатов

mapM_ :: (a -> IO b) -> [a] -> IO ()

Библиотека также предоставляет варианты с перевернутыми аргументами:

for  :: [a] -> (a -> IO b) -> IO [b]
for_ :: [a] -> (a -> IO b) -> IO ()

Итак, исходный код можно исправить следующим образом:

import Data.Foldable

files <- readProcess "ls" [] []
for_ files $ \file -> do
    md <- readProcess "mdls" [file] []
    putStrLn md
putStrLn "Complete"
Другие вопросы по тегам