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

发布于 2024-11-19 07:36:12 字数 345 浏览 6 评论 0原文

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

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

Coming from C++, I'm used to be able to build simple forms of compile-time assertions, where I could emit warnings or errors during compilation if some simple conditions (e.g. over simple algebraic expressions) weren't met via use of template meta-programming and/or cpp(1)

For instance, if I wanted to make sure my program compiles only when Int has at least a certain minBound/maxBound range or alternatively, if a loss-free (as in reversible) conversion from Int64 to Int is possible with the current compilation target. Is this possible with some GHC Haskell extension? My first guess would have been to use TH. Are there other GHC facilities that could be exploited to this end?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妥活 2024-11-26 07:36:12

且稍微简化的版本:

{-# 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

以下是 Anthony 的示例的通用 :

{-# LANGUAGE TemplateHaskell #-}
import StaticAssert

$(staticAssert False "Not enough waffles")

Here's a generalized and slightly simplified version of 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

Usage:

{-# LANGUAGE TemplateHaskell #-}
import StaticAssert

$(staticAssert False "Not enough waffles")
零崎曲识 2024-11-26 07:36:12

使用 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)

Using TH for this isn't too bad. Here is a module that defines the desired assertion as part of a vestigial declaration:

{-# 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 []]]

Using the assertion involves a top-level declaration that isn't used for anything other than the assertion:

{-# LANGUAGE TemplateHaskell #-}
import CompileTimeWarning
$(assertInt)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文