Чтобы проиллюстрировать точку с тривиальным примером, скажем, я реализовал filter
:Как взаимодействовать с чистым алгоритмом в IO коде
filter :: (a -> Bool) -> [a] -> [a]
И у меня есть предикат p
, который взаимодействует с реальным миром:
p :: a -> IO Bool
Как это сделать его работу с filter
без написания отдельной реализации:
filterIO :: (a -> IO Bool) -> [a] -> IO [a]
Предположительно, если я могу превратить p
в p'
:
p': IO (a -> Bool)
Тогда я могу сделать
main :: IO()
main = do
p'' <- p'
print $ filter p'' [1..100]
Но я не смог найти преобразование.
Отредактировано: Как человек указал в комментариях, такое преобразование не имеет смысла, так как это нарушило бы инкапсуляцию IO Монады.
Теперь вопрос в том, могу ли я структурировать свой код, чтобы чистые и IO-версии не полностью дублировали основную логику?
Он уже реализован: 'filterM'. –
Уверен, но, как сказано, это всего лишь надуманный пример. Является ли общее решение всегда реализовывать отдельно версию, которая взаимодействует с IO? Это будет очень шаблонный код для любого нетривиального алгоритма. – Chris
Я думаю, что это было бы против использования «Монады». Что означает «a -> IO Bool», так это то, что вы подаете в качестве входных данных переменную 'a' и« она выполняет некоторую «IO», возвращающую bool ». Теперь вы хотите преобразовать это в «выполнение ввода IO общей функции». Но для выполнения функции, вероятно, нужно выполнить IO. Преобразование делает - afaik - никакого смысла вообще. –