Here's an excerpt of a domain-specific file-IO function I'm writing:
let
cp :: FilePath -> IO ()
cp "." = putStr "" -- OUCH!
cp ".." = putStr "" -- CRIKEY!
cp fname = custom logic here...
in mapM_ cp filepaths
I understand mapM_
lets us drop/ignore all IO ()
results, so I'd like a cleaner alternative to putStr ""
--- ie. Haskell's "canonical" way to write "a type-correct no-op IO (or monad) expression that does nothing".
From my newbie reading I had undefined
in mind, and while this compiles and causes no issues, it gives an unwanted stdout print main.hs: Prelude.undefined
(I use stack runghc main.hs
as the sole coding environment here --- it's just sufficient for this, but the above code will be looping recursively through directory trees: so would be a good time to (re)learn about a better, or rather "the proper" way).
This is an unfortunate aspect of Haskell's learning curve: you would think there should be some sort of library function called
doNothing :: IO ()
for you to use, but the ecosystem expects you to know of the return
function in the Monad
typeclass, one of the many typeclasses that IO
instances. In this case return ()
should produce the intended behavior of creating an IO
action (read: effect, or thunk, or promise) that does nothing.
You might also be interested in listDir
and copyFile
from the path-io
package, which by using stronger types than type FilePath = String
is able to do away with the whole problem of .
and ..
altogether. Note in particular how listDir
returns subdirectories and files separately in a tuple. If that is not in the spirit of Haskell then what is? It does bring in an external dependency however but I am always looking for situations to plug that excellent library.