Изучение внутреннего устройства функций в Haskell

StackOverflow https://stackoverflow.com/questions/547922

Вопрос

Я новичок в Haskell, хотя ранее имел опыт работы с Lisp/Scheme.Прямо сейчас я просматриваю примеры из SICP и пытаюсь реализовать их на Haskell, чтобы получить больше практического опыта.В лекции 3б авторы представляют функцию для символьного вычисления производных.Он содержит, среди прочего, следующие строки:

(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?

Это было полезно?

Решение

Ваши примеры Scheme на самом деле не исследуют функции Scheme.Недавно я провел в Haskell символическую дифференциацию значений следующего типа:

data Exp a = Lit a
           | Exp a :*: Exp a
           | Exp a :+: Exp a
           | Var String
  deriving Eq

Вместо того, чтобы различать использование atom? или eq? ты используешь case (или другое сопоставление с образцом) и ==.

Другие советы

Во-первых, хотя SICP великолепен, я бы не рекомендовал его для изучения Haskell. (#) Некоторые трудности в этом вопросе проистекают из этого.

В Lisp/Scheme 'функция' рассматривается как фрагмент кода, а изучение функции означает просто изучение ее кода.В Хаскеле 'функция' означает нечто более близкое к своему математическому определению, как отображение множества А в множество Б.Так, например, в контексте Лиспа имеет смысл сравнить две функции:просто сравните их код.(Но (x+y)^2 и x^2+2*x*y+y^2 разные функции?) В Haskell это зависит от того, существует ли конструктивная процедура определения равенства для рассматриваемого вами класса функций.

Точно так же, как и в вашем вопросе, в Lisp/Scheme вы должны написать функцию «выведения», которая правильно различает заданные выражения и просто выдает ошибку или возвращает мусор на произвольных входных данных.В системе типов Haskell это (AFAIK) невозможно сделать, потому что — если вдуматься — не существует такой вещи, как дифференцирование произвольного ввода:вы можете дифференцировать только выражение (или, возможно, более общий класс, но еще не все).Итак, как и в ответе Нормана Рэмси, вы сначала определяете тип «Выражение» (или класс типа), что очень просто сделать, а затем пишете функцию

derive :: Expression -> Expression

который разбирает Expression используя конструкции сопоставления с образцом (или что-то еще, в зависимости от того, как Expressionбыли застроены).


(#):Причина в том, что у SICP совершенно другая философия, которая предполагает использование нетипизированного языка программирования и поощрение отсутствия различия между кодом и данными.Хотя аргумент «код=данные» имеет некоторые преимущества (например,тот факт, что в архитектуре фон Неймана, которую мы используем, «все равно все 0 и 1»), это не обязательно хороший способ рассуждать или моделировать проблемы.(См. книгу Филипа Уодлера. Почему расчет лучше, чем планирование подробнее об этом.) Если вы хотите прочитать книгу о Haskell с функциональным вкусом вместо Реальный мир один, возможно, Саймона Томпсона Хаскелл:Мастерство функционального программирования или Ричарда Берда Введение в функциональное программирование с использованием Haskell это лучший выбор.

Я не думаю, что ты сможешь это сделать.Лисп - это гомоиконический, Хаскель - нет.

Однако дальнейшее гугление всплыло Лискелл, который является (?) интересным гибридом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top