Проблема в том, что
ExpressionApp (termToExpression (x : xs) n) (termToExpression (x : xs) m)
делает два рекурсивных вызова, и интуитивно первый из них должен «потреблять» любое количество переменных для генерации своего вывода. После этого второй рекурсивный вызов не должен использовать переменные, уже "использованные" первым.
В некотором смысле существует какое-то состояние, которое изменяется при каждом вызове: список переменных получает частично потреблены.
Чтобы смоделировать это, вам нужно сначала написать вспомогательную рекурсивную функцию, которая возвращает вместе с новым лямбда-термином список еще не использованных переменных.
aux :: [Var] -> Term -> (Expression, [Var])
Теперь, когда вам нужно сделать два рекурсивных вызова aux
, вы можете сделать первый, получить список неиспользованных переменных из его результата и сделать второй рекурсивный вызов, используя этот список.
(Более продвинутое решение - использовать монаду State [Var]
, но я думаю, вы хотите написать базовое решение c.)