How to create an analogue of Latex providecommand in Haskell?

Viewed 68

Suppose we are importing a module M where we expect a function f1. But it may not be there. However, we do not want a compilation error, but we want to do something like the following (pseudocode):

 import M

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

In other words, I would like to make an analogue of Latex \providecommand in Haskell:

https://latexref.xyz/_005cprovidecommand.html

1 Answers

This is probably a bad idea. However, if you really want to do it, @WillemVanOnsem's suggestion will work.

You can create the following separate module to define a Template Haskell (TH) function provideCommand. Note that you have to do this in a separate module from where you want to use provideCommand because of a limitation known as the TH "stage restriction", where TH functions can't be used (technically, can't be "spliced") in the same module where they're defined.

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

This function uses lookupValueName to look up a given name at compile time. If the name is not found, it outputs some provided declarations.

You'd use it like so in some other module. You need to turn on the TemplateHaskell extension to call (i.e., "splice") provideCommand.

{-# LANGUAGE TemplateHaskell #-}

import M
import ProvideCommand

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

main = print (double 15)

If the name double is not already defined (e.g., in module M), this will define it by outputting the declarations in the quasiquote [d| ... |]. You can include multiple declarations, include for things other than double, but obviously they won't be available unless the provideCommand is triggered:

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

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