I was under the impression that using functions of type :: Name -> Q [Dec] had to be wrapped in a splice with the TemplateHaskell extension turned on, as e.g. documented in aeson:
$(deriveJSON defaultOptions ''(,,,))
But I just noticed the lens docs show using these TH functions without a splice (or TemplateHaskell), and I just tried it in a library I'm working on and it seems to work fine, even with something like this at the top level:
fmap concat $ forM [''X , ''Y , ''Z ] deriveFoo
Yet after making those modifications (removing from splice and removing pragma), I'm getting this error, unless I put a extensions: TemplateHaskell line in the test-suite block, which I don't really understand.
So is the splice thing a myth? And if so, then why do I need TemplateHaskell in an extensions list for the test-suite?
Related
I have a web application written in Haskell (using ghcjs on the client side and ghc on the server side) and I need a way to collect the CSS values which are spread throughout the modules. Currently I use a technique involving a CssStyle class and template haskell. When a module needs to export some CSS it creates a CssStyle instance for some type (the type has no significance except that it must be unique.) In the top level all the CssStyle instances are retrieved using the reifyInstances function from template haskell.
This approach has at least two drawbacks: You have to create meaningless types to attach the instances to, and you have to be sure all the instances are imported in the place where you scan and turn into real CSS. Can anyone think of a more beautiful way to collect data embedded in Haskell code?
================
Quelklef has requested some source code demonstrating the current solution:
{-# LANGUAGE AllowAmbiguousTypes, OverloadedStrings, MultiParamTypeClasses, TemplateHaskell, LambdaCase, FunctionalDependencies, TypeApplications #-}
import Clay
import Control.Lens hiding ((&))
import Data.Proxy
import Language.Haskell.TH
class CssStyle a where cssStyle :: Css
-- | Collect all the in scope instances of CssStyle and turn them into
-- pairs that can be used to build scss files. Result expression type
-- is [(FilePath, Css)].
reifyCss :: Q Exp
reifyCss = do
insts <- reifyInstances ''CssStyle [VarT (mkName "a")]
listE (concatMap (\case InstanceD _ _cxt (AppT _cls typ#(ConT tname)) _decs ->
[ [|($(litE (stringL (show tname))), $(appTypeE [|cssStyle|] (pure typ)))|] ]
_ -> []) insts)
data T1 = T1
instance CssStyle T1 where cssStyle = byClass "c1" & flexDirection row
data T2 = T2
instance CssStyle T2 where cssStyle = byClass "c2" & flexDirection column
-- Need to run this in the interpreter because of template haskell stage restriction:
--
-- > fmap (over _2 (renderWith compact [])) ($reifyCss :: [(String, Css)])
-- [("Main.T2",".c2{flex-direction:column}"),("Main.T1",".c1{flex-direction:row}")]
The point here is that any CssStyle instance from any module imported here will appear in this list, not only those defined locally.
Hmm...
I do not officially recommend your current approach. It's making use of typeclasses in a highly unorthodox way, so it's unlikely to act exactly as you like. As you've already noted, in order for it to work you need to make sure that all CssStyle instances are in scope, which is pretty arcane behaviour. Also, the current approach does not compose well, by which I mean that your css-related computation is all happening in the global context.
Unfortunately, I don't know of any canonical way to do what you want at compile-time.
However, I do have one idea. Most programs run in top-level "industrial" monads, and I'm assuming your program does as well. You could wrap your industrial monad with a new applicative (not monad) F. The role of this applicative is to allow subprograms to propagate their CSS needs to callers. Concretely, there would be a function style :: Css -> F () which acts akin to how tell acts in a writer monad. There would also be affordances to embed actions from your industrial monad into F. Then each module which has its own CSS exports its API wrapped F; doing this tracks the CSS requirements. There would be a function compileCss :: F a -> Css which builds the composite CSS style and does not execute any effectful operations embedded within F. Additionally, there would be a function execute :: F a -> IO a which executes the actions embedded in the F a value. Then main could make use of compileCss to emit the CSS, and make use of execute to separately run the program.
I admit this is somewhat awkward... wrapping all your existing code in F will be annoying at best. However, I do think it is at least correct, insofar as it tracks effects.
Perhaps the proper answer is to use an existing component-based web framework, which allows you define your component markup and styling in the same place? Some of them support emitting to static HTML.
How do I lookup type operator name? This does not work:
IssueTH.hs:
{-# LANGUAGE TemplateHaskell #-}
module IssueTH where
import Language.Haskell.TH
f :: Q [Dec]
f = do
Just n <- lookupTypeName "GHC.TypeLits.*"
return []
Issue.hs:
{-# LANGUAGE TemplateHaskell #-}
module Issue where
import IssueTH
$f
ghc Issue.hs fails with message:
Pattern match failure in do expression at IssueTH.hs
Replacing "GHC.TypeLits.*" with "GHC.TypeLits.(*)" or "*" doesn't work either.
I guess I have enough now for a brief answer. Alas I only found the reason for your problem, but not how to solve it.
My testing shows that lookupTypeName does support type operators, but only if they start with :.
Originally this was a requirement, in analogy with infix data constructors, but this was lifted to allow things like the arithmetical type operators in GHC.TypeLits. (The downside is that you can no longer have type operator variables, as were once popular for things like Arrow code.)
Presumably lookupTypeName was not updated to take this into account, and I have filed a bug report for this.
EDIT: A fix for this has finally been made, and should be in the upcoming GHC 8.2.1.
I have a module coded and working, however I can't manage to enter two function signatures for it, because to enter them I must enable the TypeFamilies extension for the module, and when I do that, it no longer builds.
For one of them I need TypeFamilies because it's using persisent/esqueleto functions.
The proper type would be, I believe:
getByIds :: (PersistEntityBackend a ~ SqlBackend) =>
EntityField a (Key a) -> [Key a] -> SqlPersistM [Entity a]
(ghc suggests a more generic signature)
The other one uses hsqml.
ghc suggests this signature but I guess it could be simplified:
prop :: forall tr b.
(Marshal tr, Typeable b, MarshalMode tr ICanReturnTo () ~ Yes) =>
String -> (b -> tr) -> Member (GetObjType (ObjRef b))
The bottom line is, that without TypeFamilies I cannot write those signatures. The moment I enable TypeFamilies, however, the code won't build, and I don't understand why. The error looks like some polymorphic functions suddenly became monomorphic.
The error output is relatively long, you can find it here.
I have TypeFamilies enabled in several other modules of the application without problems, and that enables me to write signatures using both the SqlBackend & ICanReturnTo constraints without problems.
Is there something wrong with that module that prevents it from building with TypeFamilies? Or should I enable yet another extension to fix it? I didn't expect just enabling that extension to break the compilation.
The type equality constraint ~ can only be written out if you have either TypeFamilies or GADTs enabled.
However, enabling TypeFamilies or GADTs also enables MonoLocalBinds. As the name says, it disables generalization of locally defined variables.
If MonoLocalBinds prevents code from compiling, you should either write out the generalized type signatures or factor out such locals into top-level definitions. Sometimes writing out the generalized types is a bit difficult; in such cases you can try querying GHCi, or you can enable NoMonomorphismRestriction, write unannotated top-level definitions and then look at the inferred types.
I thought there would already be a question about this, but I can't find one.
I want my program to print out the date it was compiled on. What's the easiest way to set that up?
I can think of several possibilities, but none of them are what you'd call "easy". Ideally I'd like to be able to just do ghc --make Foo and have Foo print out the compilation date each time I run it.
Various non-easy possibilities that spring to mind:
Learn Template Haskell. Figure out how to use Data.Time to fetch today's date. Find a way how to transform that into a string. (Now my program requires TH in order to work. I also need to convince it to recompile that module every time, otherwise I get the compilation date for that module [which never changes] rather than the whole program.)
Write a shell script that generates a tiny Haskell module containing the system date. (Now I have to use that shell script rather than compile my program directly. Also, shell scripting on Windows leaves much to be desired!)
Sit down and write some Haskell code which generates a tiny Haskell module containing the date. (More portable than previous idea - but still requires extra build steps or the date printed will be incorrect.)
There might be some way to do this through Cabal - but do I really want to package up this little program just to get a date facility?
Does anybody have any simpler suggestions?
Using Template Haskell for this is relatively simple.
You just need to:
Run IO action within Template Haskell monad:
runIO :: IO a -> Exp a
Then create a string literal with:
stringE :: String -> ExpQ
Put a whole expression within a quasiquote.
$( ... )
This program will print time of its compilation:
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Data.Time
main = print $(stringE =<< runIO (show `fmap` Data.Time.getCurrentTime))
You may put the relevant fragment into a module that imports all other modules to make sure it is recompiled.
Or take current revision information from your versioning system. See: TemplateHaskell and IO
The preprocessor helpfully defines __DATE__ and __TIME__ macros (just like in C), so this works:
{-# LANGUAGE CPP #-}
main = putStrLn (__DATE__ ++ " " ++ __TIME__)
This is probably simpler than Michal's suggestion of Template Haskell, but doesn't let you choose the format of the date.
I'm using GHCi 7.0.3 with the following program that implements type-level list:
{-# LANGUAGE TypeOperators #-}
data True
data False
-- List
data Nil
data Cons x xs
-- Type-level infix operator must begin with ':'
data x ::: xs
infixr 5 ::: -- set precedence level to 5 (tight)
It compiles, but when I test it with:
:t (undefined :: True:::Nil)
(what's the type of undefined when cast to type True:::Nil?) I get this error:
Illegal operator `:::' in type `True ::: Nil'
Use -XTypeOperators to allow operators in types
And indeed, when I start GHCi with the flag
-XTypeOperators
I get the expected result:
(undefined :: True ::: Nil) :: True ::: Nil
My question is: Why doesn't the equivalent pragma work:
{-# LANGUAGE TypeOperators #-}
Edit: If pragmas don't extend to GHCi environment than I have another puzzle. I tried this program:
class And b1 b2 b | b1 b2 -> b where
andf :: b1 -> b2 -> b
-- truth table
instance And True True True where andf = undefined
instance And True False False where andf = undefined
instance And False True False where andf = undefined
instance And False False False where andf = undefined
It required the following pragmas:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
But once compiled, I could use it in GHCi:
*Main> :t andf (undefined::True) (undefined::False)
andf (undefined::True) (undefined::False) :: False
I guess in the list case the interpreter couldn't even parse the expression with type-level operator :::, whereas in the case of multiparameter classes the command line was parseable. But, come to think of it, GHCi performed type inference using multi-parameter classes and functional dependencies, didn't it? This type inference is done in GHCi, and not by calling some function in the compiled code, right?
The other answers are correct about enabling the extension in GHCi, either from the GHCi prompt or as a flag when starting GHCi. There is a third option, however--you can create a .ghci file that will be loaded and run every time you start GHCi, and use that to enable the extension automatically. Particularly for things like TypeOperators, where there's very little harm in having it enabled, it's nicely convenient.
For example, here's what mine looks like right now:
:set prompt "∀x. x ⊢ "
:set -XTypeOperators
import Control.Monad
import Control.Applicative
import Control.Arrow
The .ghci file goes in whatever your system's standard location is for such files.
To answer your extended question: The code in question works in GHCi roughly because it would also work if used in another module, which imported the module using the pragmas but didn't enable them itself. GHC is more than capable of enabling extensions on a per-module basis, even when the exported definitions couldn't possibly make sense without an extension, or have inferred types that require it.
The distinction is a little fuzzy in GHCi because it also puts non-exported definitions from the module in scope, but in general anything that would work if used from another module will also work at the GHCi prompt.
Your pragma is correct; the problem is that you're trying to use it from within GHCi, which doesn't inherit the extensions of the loaded module,1 but does pass the options it's given to GHC to compile the files you list (which is why it has the same effect as the pragma).
You should keep the pragma, and either pass -XTypeOperators when you start GHCi, or enable it after loading the file as follows:
GHCi> :set -XTypeOperators
1 Which could be very undesirable, and probably impossible in many cases, for e.g. loading compiled modules.
The LANGUAGE pragma works for the source file, it is not propagated to the ghci-prompt. Since it is possible to have conflicting pragmas in multiple source files of a project, source pragmas cannot by default propagate to the ghci-prompt. It would be possible to have the pragmas from *modules effective at the prompt, I'm not sure, but I think it is pondered to implement that, anyway, so far, it's not implemented, so you need to set the extensions for ghci explicitly.