模板Haskell和隐式参数

模板Haskell和隐式参数,haskell,template-haskell,implicit-parameters,Haskell,Template Haskell,Implicit Parameters,有没有一种方法可以使用template haskell创建具有隐式参数的函数或使用隐式参数进行绑定 也就是说,是否可以使用模板haskell生成这样的签名: doSomething :: (?context :: Context) => m a 或者像这样的调用: invoc = let ?context = newContext in doSomething 我找不到合适的代数数据类型,也找不到任何函数可以帮助我解决这个问题。我正在使用GHC 7.4.2 如果template h

有没有一种方法可以使用template haskell创建具有隐式参数的函数或使用隐式参数进行绑定

也就是说,是否可以使用模板haskell生成这样的签名:

 doSomething :: (?context :: Context) => m a
或者像这样的调用:

 invoc = let ?context = newContext in doSomething
我找不到合适的代数数据类型,也找不到任何函数可以帮助我解决这个问题。我正在使用GHC 7.4.2

如果template haskell中没有对该扩展的本机支持,那么是否有其他可能在编译期间注入代码(可能类似于template haskell中的通用“代码注入函数”)

编辑:我尝试了评论中的建议,结果如下:

runQ [d| f :: (?c :: String) => Int ; f = 7 |]

<interactive>:10:17: parse error on input `c'

似乎不受支持。

这里有一种方法非常脆弱,但可以工作。当你不能参考 在haskell使用的Exp模板中,可以引用中的定义 另一个模块类似于:

reserved_prefix_x = ?x
下面是在一次ghc运行中生成上述变量的一些代码, 在ghc的第二次运行中,变量实际上是指隐式参数

{-# 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)))
你必须给ghc打两次电话,比如:

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.
尽管ghc失败,但它仍然生成GEN.hs,其中包含:

{-# LANGUAGE NoMonomorphismRestriction, ImplicitParams #-}
module GEN where
q_hithere = ?hithere
当您加载Main时,它将在那里(省略-D标志)

这种麻烦可能不值得。也许从TH调用其他程序的其他情况更能激发动机,例如对其他语言的内联调用(gfortran示例)


因为我使用了haskell src meta的默认解析器,所以Quasikote可以使用变量“reserved_prefix_x”not“?x”。应该可以不太困难地接受“?x”

你有没有试着引用一个使用隐式参数的表达式,看看你得到了什么?谢谢,我没有想到这一点;无论如何,它会抛出一个错误(请参见编辑的问题)。似乎不起作用。隐式参数似乎已经从现代haskell习语的语料库中消失了——如果它从未得到支持,我并不感到惊讶。@scravy:是的,如果引用导致错误(当然,请确保在所有相关模块中启用了扩展)这似乎很好地表明它根本不受支持。此外,就在
语言中
Exp
类型的定义下方。Haskell.TH.Syntax
模块中有。
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.
{-# LANGUAGE NoMonomorphismRestriction, ImplicitParams #-}
module GEN where
q_hithere = ?hithere
*Main> :t f_
f_ :: (?hithere::t) => t