Я бы порекомендовал Натану использовать Haskell в качестве языка спецификаций. Сам Haskell является наилучшим форматом данных для работы с функциями Haskell: -)
Но так как это интересный вопрос, я сделаю вид, что по каким-то странным причинам вам придется использовать XML. Вам нужно будет конвертировать ваш XML в настоящую функцию на Haskell. Это означает наличие некоторого отображения:
lookupFunc :: String -> ???
Который ищет функцию по имени. Вам нужно будет написать это отображение вручную или сгенерировать его с помощью Template Haskell. Но важно отметить, что ???
не является типом, и эта функция нуждается в реальном типе.
Вот аккуратный пример, похожий на ваш разнородный список, но более оптимизированный для рассматриваемой проблемы:
data SpecFunc = Result String | More (String -> SpecFunc)
Это ваш интерфейс к спецификации XML. Он говорит, что либо я закончил и уже получил результат (который уже был зачеркнут), либо мне нужен другой аргумент для продолжения (с преобразованием строки, запеченной в эту функцию). (Замечание стороны Geeky: это называется «свободная монада над (String ->)», но монадность сейчас для нас совершенно неактуальна).
Теперь мы можем написать класс типов для преобразования функций Haskell в их SpecFuncs, если их типы соответствуют нашим критериям:
class HasSpecFunc a where
toSpecFunc :: a -> SpecFunc
instance (Read a, HasSpecFunc b) => HasSpecFunc (a -> b) where
toSpecFunc f = More (\input -> toSpecFunc (f (read input)))
... -- one of these for each one of your "primitive" result types
instance HasSpecFunc String where
toSpecFunc x = Result (show x)
Используя какое-то зло, вы можете избежать указания одного экземпляра для каждого типа результата. В верхней части файла включите перекрывающиеся экземпляры:
{-# LANGUAGE OverlappingInstances #-}
Тогда используйте:
instance (Show a) => HasSpecFunc a where
toSpecFunc x = Result (show x)
Затем вы можете вызвать SpecFunc с чем-то вроде:
-- returns Nothing if the wrong number of arguments were provided
runSpecFunc :: SpecFunc -> [String] -> Maybe String
runSpecFunc (Result x) [] = Just x
runSpecFunc (More f) (x:xs) = runSpecFunc (f x) xs
runSpecFunc _ _ = Nothing
Надеюсь, это имело смысл. Но опять же, отказ от XML и использование вместо этого Haskell гораздо предпочтительнее.