Haskell pattern and implicit parameters

Is there a way to create functions with implicit parameters or link to implicit parameters using the haskell pattern?

those. Is it possible to generate such a signature using the haskell template:

doSomething :: (?context :: Context) => ma 

Or a call of this type:

  invoc = let ?context = newContext in doSomething 

I could not find suitable types of algebraic data and any functions that would help me solve this topic in the API documentation for the haskell template . I am using GHC 7.4.2.

If there is no built-in support for this extension inside the haskell template, is there another way to inject code at compile time (maybe something like the general "code insertion function" in the haskell template?).

EDIT: I tried the suggestion from the comments, here's what happens:

 runQ [d| f :: (?c :: String) => Int ; f = 7 |] <interactive>:10:17: parse error on input `c' 

then how does it work:

  runQ [d| f :: Int ; f = 7|] [SigD f_0 (ConT GHC.Types.Int),ValD (VarP f_0) (NormalB (LitE (IntegerL 7))) []] 

doesn't seem to be supported.

+6
source share
1 answer

Here is one way that is rather fragile, but it seems to work. While you can not refer to? x in Exp, which uses the haskell pattern, you can refer to the definition in another module, for example:

 reserved_prefix_x = ?x 

Below is the code that generates such variables as described above in one ghc run, and in the second ghc run the variables actually refer to implicit parameters.

 {-# LANGUAGE TemplateHaskell, NoMonomorphismRestriction #-} module GenMod (h) where import Data.Generics import Data.IORef import Data.List import Language.Haskell.Meta.Parse as P import Language.Haskell.TH import Language.Haskell.TH.Quote import Language.Haskell.TH.Syntax import qualified Data.Set as S import qualified Language.Haskell.Exts.QQ as Q import System.IO.Unsafe h = Q.hs { quoteExp = \s -> do r <- either fail (upVars . return) (P.parseExp s) writeMod' return r } pfx = "q_" {-# NOINLINE vars #-} vars :: IORef (S.Set String) vars = unsafePerformIO (newIORef S.empty) writeMod' = runIO $ writeFile "GEN.hs" . ppMod =<< readIORef vars writeMod = -- might be needed to avoid multiple calls to writeFile? -- in this example this is called for every use of `h' QuasiQuoter { quoteDec = \ _ -> do writeMod' [d| _ = () |] } ppMod xs = "{-# LANGUAGE NoMonomorphismRestriction, ImplicitParams #-}\n\ \module GEN where\n" ++ unlines (map (\x -> pfx ++ x ++ " = ?" ++ x) (S.toList xs)) upVars x = do x' <- x runIO $ modifyIORef vars (S.union (getMatchingVars x')) runIO $ print =<< readIORef vars return x' getMatchingVars = everything S.union (mkQ S.empty (\ (OccName x) -> maybe S.empty S.singleton (stripPrefix pfx x))) 

Main.hs file, which uses the quasiquater GenMod.hs:

 {-# LANGUAGE NoMonomorphismRestriction, ImplicitParams, QuasiQuotes, TemplateHaskell, CPP #-} import GenMod #ifndef stage1 import GEN #endif f_ = [h| q_hithere |] 

You need to call ghc twice, for example:

 ghci -Dstage1 Main.hs GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help [1 of 2] Compiling GenMod ( GenMod.hs, interpreted ) [2 of 2] Compiling Main ( Ex.hs, interpreted ) fromList ["hithere"] Ex.hs:8:6: Not in scope: `q_hithere' Failed, modules loaded: GenMod. 

Although ghc fails, it still generates GEN.hs, which contains:

 {-# LANGUAGE NoMonomorphismRestriction, ImplicitParams #-} module GEN where q_hithere = ?hithere 

What will be there when you load Main (leaving the -D flag)

 *Main> :t f_ f_ :: (?hithere::t) => t 

Such a problem is probably not worth it. Perhaps other situations calling other programs from TH are more motivated, for example, built-in calls to other languages http://hpaste.org/50837 (gfortran example)

Since I used the default haskell-src-meta parser, the quasi-quarter gets the use of the variables "reserved_prefix_x" not "? X". It should be possible to accept "? X" without too much difficulty.

+3
source

All Articles