2

The functions want and need both require that their input is of type FilePath rather than FilePattern. The filenames of my outputs and inputs follow a distinct pattern, outputs are _build/*checker.sh and the inputs are of ./*.py. Therefore I would rather do a want of the form:

want ['_build/*checkers.sh']

than

want ['_build/dbchecker.sh', '_build/henk_checker.sh', ..., '_build/derp_checker.sh']

I tried building a more complex want by combining getDirectoryFiles, action, need but that doesn't work since getDirectoryFiles returns Action [FilePath] rather than FilePath.

What would be the proper solution to this problem?

Henk
  • 369
  • 3
  • 9
  • 1
    Note that making `want` take a list of patterns has been requested, see https://github.com/ndmitchell/shake/issues/144. However, I don't think it's a good idea, because as you discovered in your answer, often you want to `want` a transformation over a pattern, not the results of the pattern itself. – Neil Mitchell Oct 28 '15 at 15:50
  • @NeilMitchell, maybe these kind of transformations are a nice example for in the manual/tutorial. I often need these kind of transformations. It could serve as an example of a complex `want`. – Henk Oct 28 '15 at 18:46
  • Yep, I think there need to be a better set of documentation on the website - unfortunately I'm uniquely unqualified to know what that documentation should be, since it's rarely helpful to me :) – Neil Mitchell Oct 28 '15 at 19:50

2 Answers2

2

Action, which is what getDirectoryFiles returns, seems to be a Monad, so you could use do-notation:

do
  paths <- getDirectoryFiles "" ["_build//*checkers.sh"]
  want paths

or just

getDirectoryFiles "" ["_build//*checkers.sh"] >>= want

or

want =<< getDirectoryFiles "" ["_build//*checkers.sh"]    

EDIT: as per Neil Mitchell's remarks, want needs to be replaced with need.

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
  • 1
    I guess the `return` is not needed in `return $ want paths`. – chi Oct 28 '15 at 13:08
  • oops, yes, didn't realize `want` was monadic. – Erik Kaplun Oct 28 '15 at 13:12
  • Erik, your remark about `Action` being a monad has proven to be very helpful. The problems is that action already resides within the `Rules` monad - not the other way around. Sorry, for not being specific enough. Still your help has been invaluable! – Henk Oct 28 '15 at 13:57
  • 1
    This won't work because `getDirectoryFiles` is in the `Action` monad, and `want` lives in the `Rules` monad. If you make the `want` a `need` then they are in the same monad, and can be combined. If you want to lift an `Action` to a `Rules` you can use `action`. – Neil Mitchell Oct 28 '15 at 15:49
1

Erik's remark about Action being a monad has proven to be very helpful. The problems is that action already resides within the Rules monad - not the other way around (Sorry Eric, for not being specific enough). The following code is on what I eventually settled.

import Development.Shake
import Development.Shake.Command
import Development.Shake.FilePath
import Development.Shake.Util

main :: IO ()
main = shakeArgs shakeOptions{shakeFiles="_build"} (do
  action $ do dependencies <- getDirectoryFiles "" ["*checker.py"]
              let scripts = map (\file -> "_build" </> file -<.> "sh") dependencies
              need scripts)
Henk
  • 369
  • 3
  • 9
  • 1
    In general `want` is defined as `action . need`, so here you split up the `want` and shove in a `getDirectoryFiles`. This is the recommended way (although I think I'd use a list comprehension - but an irrelevant detail). – Neil Mitchell Oct 28 '15 at 15:46