Я ищу трансформатор монады, который можно использовать для отслеживания хода выполнения процедуры. Для того, чтобы объяснить, как он будет использоваться, рассмотрим следующий код:Monad transformer для отслеживания прогресса
procedure :: ProgressT IO()
procedure = task "Print some lines" 3 $ do
liftIO $ putStrLn "line1"
step
task "Print a complicated line" 2 $ do
liftIO $ putStr "li"
step
liftIO $ putStrLn "ne2"
step
liftIO $ putStrLn "line3"
-- Wraps an action in a task
task :: Monad m
=> String -- Name of task
-> Int -- Number of steps to complete task
-> ProgressT m a -- Action performing the task
-> ProgressT m a
-- Marks one step of the current task as completed
step :: Monad m => ProgressT m()
Я понимаю, что step
должен существовать явно из-за монадических законов, и что task
должен иметь явный параметр номер шага из-за программы детерминизма/проблема с остановкой.
Монада, как описано выше, может, как я понимаю, будет реализован в одном из двух способов:
- Через функцию, которая будет возвращать текущий стек имя задачи/шаг индекса и продолжения в процедуры в той точке, в которой он остановился. Повторное вызов этой функции в возвращаемом продолжении завершит выполнение процедуры.
- Через функцию, которая предприняла действие, описывающее, что делать, когда шаг задачи завершен. Процедура будет выполняться неуправляемо до тех пор, пока она не будет завершена, «уведомляя» об окружающей среде об изменениях посредством предоставленного действия.
Для решения (1), я рассмотрел Control.Monad.Coroutine
с функцией подвески Yield
. Для решения (2) я не знаю никаких уже доступных монадных трансформаторов, которые были бы полезны.
Решение, которое я ищу, не должно иметь слишком больших служебных затрат и позволяет как можно больше контролировать процедуру (например, не требует доступа к IO или чего-то еще).
Сделайте одно из этих решений жизнеспособным, или есть другие решения этой проблемы где-то уже? Эта проблема уже решена с помощью трансформатора монады, которого я не смог найти?
EDIT: Цель состоит не в том, чтобы проверить, выполнены ли все этапы. Цель состоит в том, чтобы иметь возможность «контролировать» процесс во время его работы, чтобы можно было узнать, сколько из них было выполнено.
Вы упомянутые продолжения ... Может быть, мне не хватает чего-то очевидного, но мне интересно, можете ли вы просто использовать c ontinuation monad transformer 'ContT'. – mergeconflict
Если вы не переопределили 'putStr' и' putStrLn' с типами 'String -> ProgressT IO()', вам нужно их поднять. Для этого используйте 'liftIO'. –
Создание и отображение информации о ходе работы - система публикации/подписания. Как реализовать его под капотом будет зависеть от того, будет ли основной поток или специальный другой поток или многие другие потоки действовать на состояние прогресса. –