To illustrate the point with a trivial example, say I have implemented filter
:
filter :: (a -> Bool) -> [a] -> [a]
And I have a predicate p
that interacts with the real world:
p :: a -> IO Bool
How do it make it work with filter
without writing a separate implementation:
filterIO :: (a -> IO Bool) -> [a] -> IO [a]
Presumably if I can turn p
into p'
:
p': IO (a -> Bool)
Then I can do
main :: IO ()
main = do
p'' <- p'
print $ filter p'' [1..100]
But I haven't been able to find the conversion.
Edited: As people have pointed out in the comment, such a conversion doesn't make sense as it would break the encapsulation of the IO Monad.
Now the question is, can I structure my code so that the pure and IO versions don't completely duplicate the core logic?