Утверждения времени компиляции с GHC Haskell? - PullRequest
12 голосов
/ 11 июля 2011

Исходя из C ++, я привык создавать простые формы утверждений во время компиляции, где я мог выдавать предупреждения или ошибки во время компиляции, если некоторые простые условия (например, над простыми алгебраическими выражениями) не были выполнены с помощью использованияшаблонного метапрограммирования и / или cpp(1)

Например, если я хотел убедиться, что моя программа компилируется только тогда, когда Int имеет хотя бы определенный диапазон minBound / maxBound или, альтернативно,если возможно без потерь (как в обратимом) преобразование из Int64 в Int с текущей целью компиляции.Это возможно с некоторым расширением GHC Haskell?Моим первым предположением было бы использовать TH.Существуют ли другие объекты GHC, которые могут быть использованы для этой цели?

Ответы [ 2 ]

9 голосов
/ 11 июля 2011

Вот обобщенная и слегка упрощенная версия Пример Энтони :

{-# 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")
6 голосов
/ 11 июля 2011

Использование 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)
...