Условная компиляция в Haskell, отличная от использования CPP

#haskell #c-preprocessor #conditional-compilation

#haskell #c-препроцессор #условная компиляция

Вопрос:

Расширения CPP допускают условную компиляцию, например

 {-# LANGUAGE CPP #-}
#ifdef DEBUG
-- some debug code
#endif
 

Конечно, это работает нормально, но это довольно неуклюже и неидиоматично. Неужели нет другого механизма для достижения условной компиляции?

(Конкретный случай, когда я действительно хотел бы его использовать, — это Text.Megaparsec.Функция Debug.dbg. Создаваемый им синтаксический анализ действительно полезен, но исходный код замусорен #ifdef #endif шумом, что делает все это довольно нечитаемым. Функция-оболочка в верхней части удалит большую часть шума, но, тем не менее, мне интересно.)

Комментарии:

1. Я бы сказал, что CPP является распространенным способом достижения условной компиляции. Я бы также сказал, что CPP на данный момент является идиоматическим способом. Другим вариантом является шаблон Haskell, который в некоторых случаях может использоваться для этой цели, но я никогда не видел, чтобы он использовался как таковой.

2. Другим потенциальным вариантом было бы использовать Backpack . Поместите функцию отладки в сигнатуру модуля, затем напишите две внутренние библиотеки с реализациями: одна, которая не работает, другая, которая делегирует истинную функцию отладки.

Ответ №1:

Легкое решение — использовать CPP только один раз для определения логического значения, которое затем можно использовать в обычном коде Haskell:

 #ifdef DEBUG
#define debug True
#else
#define debug False
#fi
 

или макрос, если вы даже не хотите, чтобы отладочный код проходил проверку типов.


Другой способ выполнить условную компиляцию без CPP — это изменить источник модулей на уровне пакета, хотя я не знаю ни одного реального примера этого.

Создайте два модуля с одинаковым именем debug/Debug.hs и nodebug/Debug.hs оба экспортируют, например, логическое debug :: Bool значение .

В конфигурации пакета добавьте флаг для выбора между debug/ и nodebug/ .

 flag debug
  description: debug mode
  default: False
  manual: True

library
  ...
  if flag(debug)
    hs-source-dirs: debug
  else
    hs-source-dirs: nodebug
 

Теперь вы можете создать библиотеку с -f debug помощью, чтобы включить отладку.