使用GHC Haskell进行编译时断言?

时间:2011-07-11 10:26:20

标签: haskell ghc compile-time

来自C ++,我习惯于能够构建简单形式的编译时断言,如果通过使用不满足某些简单条件(例如,通过简单的代数表达式),我可以在编译期间发出警告或错误模板元编程和/或cpp(1)

例如,如果我想确保我的程序仅在Int至少具有某个minBound / maxBound范围时进行编译,或者如果是无损失的(如在可逆的)使用当前编译目标可以从Int64转换为Int。这可能是GHC Haskell扩展的一部分吗?我的第一个猜测是使用TH。是否有其他GHC设施可以用于此目的?

2 个答案:

答案 0 :(得分:9)

以下是Anthony's example的广义和略微简化版本:

{-# LANGUAGE TemplateHaskell #-}
module StaticAssert (staticAssert) where

import Control.Monad (unless)
import Language.Haskell.TH (report)

staticAssert cond mesg = do
    unless cond $ report True $ "Compile time assertion failed: " ++ mesg
    return [] -- No need to make a dummy declaration

用法:

{-# LANGUAGE TemplateHaskell #-}
import StaticAssert

$(staticAssert False "Not enough waffles")

答案 1 :(得分:6)

使用TH来做到这一点并不算太糟糕。这是一个模块,它定义了所需的断言作为残留声明的一部分:

{-# LANGUAGE TemplateHaskell #-}
module CompileTimeWarning where
import Control.Monad (unless)
import Data.Int (Int64)
import Language.Haskell.TH

assertInt = let test = fromIntegral (maxBound::Int) == (maxBound::Int64)
            in do unless test $ report True "Int is not safe!"
                  n <- newName "assertion"
                  e <- fmap NormalB [|()|]
                  return $ [FunD n [Clause [] e []]]

使用断言涉及一个顶级声明,该声明不用于断言以外的任何内容:

{-# LANGUAGE TemplateHaskell #-}
import CompileTimeWarning
$(assertInt)