Утверждения времени компиляции с GHC Haskell?
Исходя из С++, я привык к тому, чтобы создавать простые формы утверждений времени компиляции, когда я мог генерировать предупреждения или ошибки во время компиляции, если некоторые простые условия (например, над простыми алгебраическими выражениями) не выполнялись с использованием метапрограмм шаблона и/или cpp(1)
Например, если бы я хотел убедиться, что моя программа компилируется только тогда, когда Int
имеет по крайней мере определенный диапазон minBound
/maxBound
или, альтернативно, если без потерь (как в обратимом) преобразовании из Int64
до Int
возможно с текущей целью компиляции. Возможно ли это с некоторым расширением GHC Haskell? Мое первое предположение заключалось в том, чтобы использовать TH. Существуют ли другие объекты GHC, которые можно использовать с этой целью?
Ответы
Ответ 1
Здесь обобщенная и слегка упрощенная версия примера Энтони:
{-# 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")
Ответ 2
Использование 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)