The problem is in the loop body: <$>
applies HT.insert
and abort
to the result of the HT.lookup
action, but the resulting IO actions are then simply discarded by forM_
as values, without being used or executed.
This is similar to saying:
putStrLn <$> getLine -- has type IO (IO ())
This action yields a separate IO action as its result. Executing it and discarding its result will end up executing only the getLine
, and not the putStrLn
.
Correcting this requires using join
, or equivalently using =<<
as the application operator instead of <$>
:
putStrLn =<< getLine -- has type IO ()
This combines the two actions into a single action, as expected.