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

hvr*_*hvr 12 haskell ghc compile-time

从C++来了,我曾经是能够建立编译时断言,在那里我可以在编译时发出警告或错误的简单形式,如果一些简单的条件(例如在简单的代数表达式)未通过使用模板元的满足 - 编程和/或 cpp(1)

举例来说,如果我想确保我的程序时,只编译Int至少有一定的minBound/ maxBound范围或替代,如果从(如可逆)无损耗转换Int64Int可能与当前编译目标.这可能是GHC Haskell扩展的一部分吗?我的第一个猜测是使用TH.是否有其他GHC设施可以被利用?

ham*_*mar 9

这是Anthony的例子的一般化和略微简化的版本:

{-# 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
Run Code Online (Sandbox Code Playgroud)

用法:

{-# LANGUAGE TemplateHaskell #-}
import StaticAssert

$(staticAssert False "Not enough waffles")
Run Code Online (Sandbox Code Playgroud)

  • 即使它是可选的,也可以*统一地使用拼接语法. (5认同)

Ant*_*ony 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 []]]
Run Code Online (Sandbox Code Playgroud)

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

{-# LANGUAGE TemplateHaskell #-}
import CompileTimeWarning
$(assertInt)
Run Code Online (Sandbox Code Playgroud)