This is probably a bad idea. However, if you really want to do it, @WillemVanOnsem's suggestion will work.
You can create the following separate module to define a Template Haskell (TH) function provideCommand
. Note that you have to do this in a separate module from where you want to use provideCommand
because of a limitation known as the TH "stage restriction", where TH functions can't be used (technically, can't be "spliced") in the same module where they're defined.
module ProvideCommand where
import Language.Haskell.TH
provideCommand :: String -> Q [Dec] -> Q [Dec]
provideCommand nam defn = do
mval <- lookupValueName nam
case mval of
Just _ -> return []
Nothing -> defn
This function uses lookupValueName
to look up a given name at compile time. If the name is not found, it outputs some provided declarations.
You'd use it like so in some other module. You need to turn on the TemplateHaskell
extension to call (i.e., "splice") provideCommand
.
{-# LANGUAGE TemplateHaskell #-}
import M
import ProvideCommand
provideCommand "double" [d| double x = x * 2 |]
main = print (double 15)
If the name double
is not already defined (e.g., in module M
), this will define it by outputting the declarations in the quasiquote [d| ... |]
. You can include multiple declarations, include for things other than double
, but obviously they won't be available unless the provideCommand
is triggered:
provideCommand "double"
[d| double :: Int -> Int
double 0 = 0
double n = addTwo (double (n-1))
addTwo :: Int -> Int
addTwo x = x + 2
|]
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…