如何在 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
的模拟:
这可能是个坏主意。但是,如果您真的想这样做,@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
|]
假设我们正在导入一个模块 M
,我们希望其中有一个函数 f1
。但它可能不存在。但是,我们不希望出现编译错误,而是希望执行如下操作(伪代码):
import M
f2 = if (defined f1) then f1 else ...
换句话说,我想在 Haskell 中制作 Latex \providecommand
的模拟:
这可能是个坏主意。但是,如果您真的想这样做,@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
|]