GHC的最新版本具有新的“插件”功能,您可以在其中编写普通的Haskell代码,像往常一样对其进行编译,然后将其插入到编译器中,以使其能够处理GHC的内部状态。
这是非常酷。但是,有一个小障碍:要执行此操作,必须已编译插件(似乎很明显)并将其注册为软件包DB中的软件包!
插件完成后就可以了;将其打包并放在Hackage上,以供所有人欣赏。但是,在尝试开发软件包时如何解决呢?在每次编辑时,您都必须手动注销旧软件包,构建新软件包并进行注册,您的edit-compile-execute周期如何工作?
基本上,在尝试开发插件时,有什么方法可以避开此要求?
如果您使用 Cabal,它应该会为您管理一切:
my-plugin.cabal
cabal-version: 2.4
name: my-plugin
version: 1.0.0.0
library
build-depends: base ^>= 4.12.0.0
, ghc ^>= 8.6.1
hs-source-dirs: src
exposed-modules: MyPlugin
-- could also be an internal library, executable, etc
test-suite test-plugin
type: exitcode-stdio-1.0
-- the dependency on my-plugin is everything, placing it
-- in the package DB of the GHC compiling this test
build-depends: base, my-plugin
hs-source-dirs: test
ghc-options: -fplugin=MyPlugin
main-is: Main.hs
Run Code Online (Sandbox Code Playgroud)
src/MyPlugin.hs
module MyPlugin(plugin) where
import GhcPlugins
-- this is an example plugin from the manual
-- it prints the names of the non-recursive bindings in each module
plugin :: Plugin
plugin = defaultPlugin {
installCoreToDos = install
}
install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install _ todo = do
return (CoreDoPluginPass "Say name" pass : todo)
pass :: ModGuts -> CoreM ModGuts
pass guts = do dflags <- getDynFlags
bindsOnlyPass (mapM (printBind dflags)) guts
where printBind :: DynFlags -> CoreBind -> CoreM CoreBind
printBind dflags bndr@(NonRec b _) = do
putMsgS $ "Non-recursive binding named " ++ showSDoc dflags (ppr b)
return bndr
printBind _ bndr = return bndr
Run Code Online (Sandbox Code Playgroud)
test/Main.hs
module Main where
import Numeric.Natural
import Prelude hiding (even, odd)
-- printed
x :: Int
x = 5
-- not printed
fixObvious :: (a -> a) -> a
fixObvious f = f (fixObvious f)
-- printed
fixSubtle :: (a -> a) -> a
fixSubtle f = let x = f x in x
-- neither printed
even, odd :: Natural -> Bool
even 0 = True
even n = odd (n - 1)
odd 0 = False
odd n = even (n - 1)
-- printed
main :: IO ()
main = return ()
-- if the plugin were more interesting, you may want to test that any
-- modified definitions act like you expect them to
Run Code Online (Sandbox Code Playgroud)