如何在Template Haskell读取的文本文件变更时强制Stack重新编译?
问题描述
我正在编写xmonad配置,为实现可切换的配色主题,将每个主题定义为类型(如data Dracula = Dracula),并创建了ColorTheme类型类:
class ColorTheme a where colorWhite::a->String colorWhite = const "#ffffff" -- 其余颜色定义
我希望通过dmenu脚本切换主题:脚本将选中的主题名称写入theme.txt文件(文件名对应主题类型的字符串表示)。借助Template Haskell,我已实现从文件读取字符串并转换为构造函数:
theme.txt内容:
Dracula
TH.Theme模块代码:
{-# LANGUAGE TemplateHaskell #-} module TH.Theme where import Language.Haskell.TH import System.IO import Language.Haskell.TH.Syntax retrieveThemeName = do handle <- openFile "theme.txt" ReadMode name <-hGetLine handle return $ LitE (StringL name )
Colors.Theme模块代码:
{-# LANGUAGE TemplateHaskell #-} module Theme( module Theme, module Colors ) where import Colors import Language.Haskell.TH import TH.Theme import GHC.IO (unsafePerformIO) import Language.Haskell.TH.Syntax theme = $(conE (mkName $(runIO retrieveThemeName )))
当前问题:当theme.txt文件内容变更时,Stack不会自动触发重新编译。我知道Language.Haskell.TH.Syntax模块中的addDependentFile函数可以解决这个问题,但不清楚正确的使用方式,也没找到相关示例。
我曾尝试在xmonad.hs的main函数中调用该函数:
-- xmonad.hs main :: IO () main = (xmonad . withSB mySB . docks . ewmhFullscreen . ewmh $ defaults) >> (runQ $ addDependentFile "/absolute_path/to/theme.txt")
但运行时抛出异常,提示无法在IO monad中调用Q monad。
环境信息
- GHC版本:9.2.4
- Stack版本:2.9.1
解决方案
修改retrieveThemeName函数,将addDependentFile调用放在Template Haskell的Q monad上下文内,同时调整代码结构:
retrieveThemeName :: Q Exp retrieveThemeName = do addDependentFile "/absolute_path/to/theme.txt" runIO $ do handle <- openFile "theme.txt" ReadMode name <- hGetLine handle return $ LitE (StringL name)
然后在Colors.Theme模块中使用该函数:
theme = $(conE (mkName $(retrieveThemeName)))
内容的提问来源于stack exchange,提问作者Kareem Taha
相关产品推荐
相关产品推荐

