Неблокирующее IO с Haskell [дубликат]


Возможный дубликат:
какова реакция Хаскелла на узел?js?
Как я могу смотреть несколько файлов / сокетов, чтобы стать читаемым/доступным для записи в Haskell?

Можно ли написать программу Haskell, которая выполняет ввод-вывод неблокирующим способом, как в nodejs?

Например, я хотел бы получить 10 записей из базы данных, которая находится далеко, поэтому я хотел бы запустить 10 запросов одновременно, и когда результат будет доступен, то верните эту коллекцию. Монада IO не поможет, потому что монада явно сериализует вычисления с помощью bind. Я думаю, что стиль передачи продолжения, в котором вы передаете вычисление, которое вы хотите затем, имеет ту же проблему, снова он сериализует вычисление. Я не хочу работать с потоками, я ищу другое решение. Возможно ли это?

2 3

2 ответа:

Нити Хаскелла имеют чрезвычайно малый вес. Более того, GHCs IO monad большую часть времени использует событийное планирование, что означает, что обычный код Хаскелла похож на узел стиля передачи продолжения.JS-код (компилируется только в машинный код и выполняется с несколькими процессорами...)

Ваш пример тривиален

import Control.Concurrent.Async

--given a list of requests
requests :: [IO Foo]

--you can run them concurrently
getRequests :: IO [Foo]
getRequests = mapConcurrently id requests

Control.Concurrent.Async Вероятно, это именно то, что вы ищете в отношении библиотеки для будущего. Хаскелл никогда не должен задыхаться от простых тысяч (обычных) нитей. Я никогда этого не делал. написан код, который использует миллионы потоков ввода-вывода, но я думаю, что ваши единственные проблемы будут связаны с памятью.

Чтобы конкретизировать комментарии к Control.Concurrent.Async, Вот пример использования async пакет.

import Network.HTTP.Conduit
import Control.Concurrent.Async

main = do
    xs <- mapM (async . simpleHttp) [ "www.stackoverflow.com"
                                    , "www.lwn.net"
                                    , "www.reddit.com/r/linux_gaming"]
    [so,lwn,lg] <- mapM wait xs
    -- parse these how ever you'd like
Таким образом, в приведенном выше примере мы определяем три запроса HTTP get для трех различных веб-сайтов, запускаем эти запросы асинхронно и ждем завершения всех трех, прежде чем продолжить.