如何在 Haskell 中创建 Latex providecommand 的模拟?

How to create an analogue of Latex providecommand in Haskell?

假设我们正在导入一个模块 M,我们希望其中有一个函数 f1。但它可能不存在。但是,我们不希望出现编译错误,而是希望执行如下操作(伪代码):

 import M

 f2 = if (defined f1) then f1 else ...

换句话说,我想在 Haskell 中制作 Latex \providecommand 的模拟:

https://latexref.xyz/_005cprovidecommand.html

这可能是个坏主意。但是,如果您真的想这样做,@WillemVanOnsem 的建议会奏效。

您可以创建以下单独的模块来定义模板 Haskell (TH) 函数 provideCommand。请注意,由于称为 TH“阶段限制”的限制,您必须在要使用 provideCommand 的单独模块中执行此操作,其中不能使用 TH 函数(从技术上讲,不能“拼接”)在定义它们的同一模块中。

module ProvideCommand where

import Language.Haskell.TH

provideCommand :: String -> Q [Dec] -> Q [Dec]
provideCommand nam defn = do
  mval <- lookupValueName nam
  case mval of
    Just _ -> return []
    Nothing -> defn

此函数使用 lookupValueName 在编译时查找给定名称。如果找不到名称,它会输出一些提供的声明。

您可以像在其他模块中那样使用它。您需要打开 TemplateHaskell 分机才能呼叫(即“拼接”)provideCommand.

{-# LANGUAGE TemplateHaskell #-}

import M
import ProvideCommand

provideCommand "double" [d| double x = x * 2 |]

main = print (double 15)

如果名称 double 尚未定义(例如,在模块 M 中),这将通过输出准引用 [d| ... |] 中的声明来定义它。您可以包括多个声明,包括 double 以外的内容,但显然它们将不可用,除非 provideCommand 被触发:

provideCommand "double"
  [d| double :: Int -> Int
      double 0 = 0
      double n = addTwo (double (n-1))

      addTwo :: Int -> Int
      addTwo x = x + 2
  |]