You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:25:21