Как мне вывести значения из списка по мере их расчета?

У меня есть длительное вычисление, которое выводит список. Я хочу выводить значения из этого списка по мере их вычисления. Какой был бы аккуратный способ сделать это?

В настоящее время я использую mapM_ print для печати каждого значения в STDOUT. Это работает достаточно хорошо для простого случая вывода значений в командную строку, но кажется немного хакерским и сложным в работе.

Кроме того, в какой-то момент я хочу превратить вывод командной строки в интерактивную визуализацию. Как я мог превратить свой список в нечто вроде потока событий из FRP? Было бы здорово подключить это к существующей структуре графического интерфейса в качестве источника событий.

Можно переписать функцию так, чтобы она использовала не список, а что-то другое, хотя решение, позволяющее мне использовать список как есть, было бы идеальным.


person Tikhon Jelvis    schedule 06.01.2013    source источник
comment
Поскольку списки в Haskell ленивы и mapM_ тоже хорошо с ними работает, я думаю, что решение по умолчанию вполне неплохое. Просто используйте hFlush stdout, чтобы убедиться, что вывод действительно очищен (например, mapM_ (hFlush stdout << print).   -  person Dmytro Sirenko    schedule 06.01.2013


Ответы (1)


Это работа для итераторов и итераторов, таких как библиотеки.

Использование библиотеки Proxy.

import Control.Proxy

runProxy $ fromListS [1..10] >-> <processing> >-> printD >-> <more> processing>

Где <processing> — дополнительные расчеты, которые необходимо выполнить.

Похожие вопросы: ленивая версия mapM, Не ленив ли mapM в Haskell?

Например:

> labeledPrint label x = putStrLn $ label ++ show x
> runProxy $ fromListS [1..4] >-> printD >-> mapD (*2) 
                              >-> useD (labeledPrint "Second printer: ")
1
Second printer: 2
2
Second printer: 4
3
Second printer: 6
4
Second printer: 8

Если вы измените порядок применения и используете <-< вместо >->, то это будет выглядеть как обычное приложение функции.

runProxy $ useD (labeledPrint "Second printer: ") <-< mapD (*2)
                                                  <-< printD
                                                  <-< fromListS [1..4]
person Davorak    schedule 06.01.2013
comment
Вы также можете использовать useD вместо mapMD, если не хотите изменять значение, передаваемое вниз по течению. - person Gabriel Gonzalez; 07.01.2013