> To unsubscribe from this group and stop receiving emails from it, send an email to shake-build-system+unsub...@googlegroups.com.
Hi,
Building on the examples, I have tried a number of things with little success:
import Development.Shake
import Development.Shake.Classes
import Development.Shake.Command
import Development.Shake.FilePath
import Development.Shake.Util
main :: IO ()
newtype UrlLastModified = UrlLastModified () deriving
(Show,Typeable,Eq,Hashable,Binary,NFData)
type instance RuleResult UrlLastModified = String
Will not compile:
Shakefile.hs:11:1: error:
• Illegal family instance for ‘RuleResult’
(Use TypeFamilies to allow indexed type families)
• In the type instance declaration for ‘RuleResult’
I can compile instead the following type:
newtype UrlLastModified = UrlLastModified () deriving (Show,Typeable,Eq)
Then go ahead and define the oracle:
addOracle $ \(UrlLastModified _) -> do
fmap fromStdout $ cmd Shell "curl --silent --head
http://hackage.haskell.org/package/shake-0.18.2/shake-0.18.2.tar.gz
| grep -i last.modified" :: Action String
Which will fail to compile with the following error:
Shakefile.hs:29:6: error:
• Couldn't match type ‘RuleResult UrlLastModified’ with
‘[Char]’
arising from a use of ‘addOracle’
Finally, I can define my new type as a String:
newtype UrlLastModified = UrlLastModified String deriving
(Show,Typeable,Eq)
Then add an Oracle:
addOracle $ \(UrlLastModified _) -> do
Stdout lastModified <- cmd Shell "curl --silent --head
http://hackage.haskell.org/package/shake-0.18.2/shake-0.18.2.tar.gz
| grep -i last.modified"
return lastModified
But then I fail when asking:
"//*.tar.gz" %> \out -> do
lastModified <- askOracle (UrlLastModified)
cmd_ "wget" "--quiet"
["http://hackage.haskell.org/package/shake-0.18.2/" ++ out]
With the following error:
Shakefile.hs:38:24: error:
• No instance for (Show (RuleResult (String ->
UrlLastModified)))
arising from a use of ‘askOracle’
Is it so, that I always need an Action String as a result from my
Oracle?
OK I think I got this. The following works:
Adding the following to the .hs file header:
{-# LANGUAGE TypeFamilies, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
Then, the normal type declaration as shown in the examples:
newtype UrlLastModified =
UrlLastModified () deriving
(Show,Typeable,Eq,Hashable,Binary,NFData)
type instance RuleResult UrlLastModified = String
I added the oracle using this one-liner (Shell option is important):
addOracle $ \(UrlLastModified _) -> fmap fromStdout $
cmd Shell "curl --silent --head
http://hackage.haskell.org/package/shake-0.18.2/shake-0.18.2.tar.gz
| grep -i last.modified" :: Action String
Here I would like to know how can I format this better into
multiple lines, ultimately how can this be parameterized also. Why
does this need to return an Action String?
And one day when I grow up, I might even use Haskell libraries for
the HTTP request instead of dirty,dirty shell.
"//*.tar.gz" %> \out -> do
lastModified <- askOracle (UrlLastModified ())
cmd_ "wget" "--quiet" [shakeUrl ++ out]
I believe this covers the main issue of up-to-dateness of a file located at an URL.
The specific HTTP request and how to interpret it might change, but I think this is very important as here we are really doing something that cannot be done with Make and others, while keeping it functional *.
- >The SHA SUM calculation would be also good to add. We can
have the downloaded shasum file as a dependency, but what is the
best way to double-check with the already downloaded file? Because
technically, by the time we figure out our file has not the same
checksum, the file would be already downloaded.
* (One can also create targets that are always run with Make. I have never liked that those targets exist, because from an automation point of view the files depending on them are technically never up-to-date).