Изучение внутренних функций в Хаскелле
Я новичок в Хаскелле, хотя и имел предыдущий опыт работы с Lisp/Scheme. Прямо сейчас я смотрю на примеры из SICP и пытаюсь реализовать их в Haskell, чтобы получить больше практического опыта. В лекции 3b авторы представляют функцию для вычисления производных символически. Он содержит, среди прочего, следующие строки:
(define (deriv exp var)
(cond ((constant? exp var) 0)
((same-var? exp var) 1)
; ...
Далее в лекции определяются еще некоторые функции:
(define (constant? exp var)
(and (atom? exp)
(not (eq? exp var))))
Есть ли способ сделать то же самое в Haskell, т. е. проверить атомарность а символическая эквивалентность какой-то другой функции? Или в более общем плане, каковы средства "разборки" функций в Haskell?
3 ответа:
Ваши примеры схем на самом деле не исследуют функции схемы. Недавно я провел некоторую символическую дифференциацию в Haskell по значениям следующего типа:
data Exp a = Lit a | Exp a :*: Exp a | Exp a :+: Exp a | Var String deriving Eq
Вместо различения с помощью
atom?
илиeq?
вы используетеcase
(или другое сопоставление шаблонов) и==
.
Во-первых, хотя SICP велик, я бы рекомендовал не использовать его для изучения Хаскелла.( # ) Некоторые трудности в этом вопросе проистекают из этого.
В Lisp/Scheme "функция" мыслится как часть кода, и изучение функции просто означает изучение ее кода. В Haskell, A 'function' означает нечто более близкое к его математическому определению, как отображение из множества A в множество B. Так, например, в контексте Lisp имеет смысл сравнить две функции: просто сравните их код. (Но являются ли
Точно так же, как и в вашем вопросе, в Lisp/Scheme вы бы написали функцию "derive", которая правильно дифференцирует заданные выражения и просто выдает ошибки или возвращает мусор на произвольных входах. В соответствии с системой типов Хаскелла это (AFAIK) невозможно сделать, потому что-если вы думаете об этом-нет такой вещи, как дифференцирование произвольного входного сигнала: вы можете дифференцировать только выражение (или, возможно, более общий класс, но все же не все). Итак, как и в ответе Нормана Рэмси, вы сначала определяете тип "выражения" (или класс типа), что очень просто сделать, а затем пишете функцию(x+y)^2
иx^2+2*x*y+y^2
различными функциями?) В Хаскелле это зависит от того, существует ли конструктивная процедура определения равенства для рассматриваемого класса функций.derive :: Expression -> Expression
, который разбирает
Expression
, используя соответствующие шаблону конструкции (или что-то еще в зависимости от того, как были построеныExpression
s).
(#): причина в том, что SICP имеет совершенно иную философию, которая предполагает использование нетипизированного языка программирования и поощряет отсутствие различия между кодом и данными. Хотя аргумент "код=данные" имеет некоторые достоинства (например, тот факт, что в архитектуре фон Неймана мы используем "все равно 0 и 1"), это не обязательно хороший способ рассуждения о проблемах или моделирования. (Подробнее об этом см. статью Филиппа Уодлера " почему расчет лучше, чем интрига".) Если хотите для чтения книги Хаскелла с функциональным вкусом вместореального мира , возможно, лучшим выбором будет книга Саймона ТомпсонаHaskell: the Craft of Functional Programming или Ричарда Бердавведение в функциональное программирование с использованием Haskell .
Я не думаю, что ты сможешь это сделать. Лисп-это гомойконический , Хаскелл-нет.
Однако, дальнейшее гугление оказалось Liskell , который (?) интересный гибрид.