Haskell: не получить это с IO [FilePath] - PullRequest
4 голосов
/ 15 мая 2011

Работа с учебниками и т. Д. В ghci - пока все хорошо. Хотя я чего-то совершенно упускаю: моя функция создает IO [FilePath] «вещь». В ghci это выглядит так:

["xml","velocity.log.1","velocity.log"] (список сокращен для краткости)

Я вижу, что функция делает то, что я хочу. Следующий шаг - я хочу «распечатать» это сам.

Ничто из того, что я делаю, не позволяет мне напечатать результат. Я не хочу увековечивать свои привычки Java / C # / Python в Haskell - в этом нет смысла. Я полагаю, что есть веская причина, по которой Хаскелл делает все по-другому, но я не понимаю, как получить (ограниченное) значение из этой функции.

module Main (
    main
) where

import RecursiveContents

main = do putStrLn "this"
          getRecursiveContents "/home/xyz/myDir"

Это работает. Но что, если я хочу, чтобы main напечатал результат getRecursiveContents "/home/xyz/myDir"?

В ghci я могу просто набрать / вставить getRecursiveContents "/home/xyz/myDir", и материал извергается - что мне нужно сделать, чтобы самому его напечатать?

Если я это сделаю:

let xyz = getRecursiveContents "/home/xyz/myDir" в ghci, единственное, что я могу сделать с xyz, это тип: xyz <enter> и посмотрите результат.

Я не могу делать голову, хвост и т. Д. И т. Д. Я знаю, что IO [FilePath] - это нечто особенное, а не то же самое, что массив или список [a] - но я ничего не делаю, помогая мне понять, как пройти мимо этого

Я, должно быть, что-то упускаю - что-то, чего не могу найти в Learn You a Haskell или Real World Haskell . Разве я не в правильном месте?

Любые отзывы или допинг приветствуются.

Ответы [ 3 ]

9 голосов
/ 15 мая 2011

Чтобы получить результаты действия ввода-вывода (т. Е. Запустить действие), вы связываете результаты вычисления IO с переменной:

Предполагая:

getRecursiveContents :: FilePath -> IO String

Тогда вы можете просто напечатать результат:

main = do str <- getRecursiveContents "/home/xyz/myDir"
          print str

Очевидно, что это всего лишь пример, но когда функция на самом деле состоит из двух строк, люди обычно не используют запись do и избегаютявно указав промежуточную переменную str:

main = getRecursiveContents "/home/xyz/myDir" >>= print
5 голосов
/ 15 мая 2011

Используйте <- в нотации, чтобы добраться до [FilePath]. Затем вы можете манипулировать им с помощью любых функций списка, если у вас есть какое-то действие IO.

main = do putStrLn "this"
          contents <- getRecursiveContents "/home/xyz/myDir"
          print contents

В качестве альтернативы вы можете использовать >>= для передачи результатов одного действия IO в другое. Это одно и то же, просто написано по-другому.

main = do putStrLn "this"
          getRecursiveContents "/home/xyz/myDir" >>= print

Более подробное объяснение см. В главах ввода / вывода


Причина, по которой он работает в GHCi, заключается в том, что когда GHCi оценил ваше выражение, он смотрит на тип. Если это IO a, он запустит действие и отобразит результат автоматически, тогда как в реальной программе вы должны сделать это самостоятельно. См. Руководство пользователя GHC .

4 голосов
/ 15 мая 2011

Вы можете связать значения в до блоков.Это также место, где вы можете применять чистые функции (например, show, tail и т. Д.):

main = do putStrLn "this"
          x <- getRecursiveContents "/home/xyz/myDir"
          putStrLn (show x)

Если foo имеет тип IO a, то вам нужно что-то вроде do и x <- foo дляполучить значение.</p>

Для получения дополнительной информации обратитесь к любому учебнику по монаде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...