Haskell или Standard ML для начинающих?

Я собираюсь преподавать курс более низкого уровня в дискретных структурах. Я выбрал текстовую книгу Discrete Structures, Logic и Computability частично потому, что в ней содержатся примеры и концепции, способствующие реализации с функциональным программированием язык. (Я также считаю это хорошим учебником.)

Я хочу простой для понимания язык FP, чтобы проиллюстрировать концепции DS и что студенты могут использовать. В лучшем случае у большинства студентов будет только один или два семестра программирования на Java. Посмотрев на Схему, Erlang, Haskell, Ocaml и SML, я поселился в Haskell или Standard ML. Я склоняюсь к Haskell по причинам, изложенным ниже, но мне хотелось бы мнение тех, кто является активным программистом в том или ином.

  • Оба Haskell и SML имеют сопоставление с образцом, что позволяет описать рекурсивный алгоритм cinch.
  • Haskell имеет приятные списки, которые хорошо сочетаются с тем, как эти списки выражаются математически.
  • У Haskell есть ленивая оценка. Отлично подходит для построения бесконечных списков, используя технику понимания списка.
  • SML имеет действительно интерактивный интерпретатор, в котором функции могут быть определены и использованы. В Haskell функции должны быть определены в отдельном файле и скомпилированы перед использованием в интерактивной оболочке.
  • SML дает явное подтверждение аргументов функции и возвращаемых типов в синтаксисе, который легко понять. Например: val foo = fn: int * int → int. Синтаксис неявного каркаса Haskell немного тупые, но не совсем чужды. Например: foo:: Int → Int → Int.
  • Haskell по умолчанию использует произвольные числа точности. Это внешняя библиотека в SML/NJ. И SML/NJ усекает вывод по 70 символов по умолчанию.
  • Синтаксис лямбда Haskell тонкий - он использует один обратный слэш. SML является более явным. Не уверен, что нам когда-нибудь понадобится лямбда в этом классе.

По существу, SML и Haskell примерно эквивалентны. Я склоняюсь к Haskell, потому что я люблю списки и бесконечные списки в Haskell. Но я обеспокоен тем, что обширное количество символов в компактном синтаксисе Haskell может вызвать проблемы со студентами. Из того, что я собрал, читал другие сообщения на SO, Haskell не рекомендуется начинающим начинающим с FP. Но мы не собираемся создавать полноценные приложения, просто пытаемся простыми алгоритмами.

Как вы думаете?


Изменить: прочитав некоторые из ваших замечательных ответов, я должен уточнить некоторые из моих пунктов.

В SML нет синтаксического различия между определением функции в интерпретаторе и ее определением во внешнем файле. Скажем, вы хотите написать факториальную функцию. В Haskell вы можете поместить это определение в файл и загрузить его в GHCi:

fac 0 = 1
fac n = n * fac (n-1)

Для меня это ясно, красно и соответствует математическому определению в книге. Но если вы хотите напрямую написать функцию в GHCi, вам нужно использовать другой синтаксис:

let fac 0 = 1; fac n = n * fac (n-1)

При работе с интерактивными переводчиками с точки зрения обучения это очень удобно, когда ученик может использовать один и тот же код как в файле, так и в командной строке.

Под "явным подтверждением функции" я имел в виду, что после определения функции SML сразу сообщает вам имя функции, типы аргументов и тип возвращаемого значения. В Haskell вам нужно использовать команду :type, а затем вы получите несколько запутанную нотацию карри.

Еще одна интересная вещь о Haskell - это правильное определение функции:

fac 0 = 1
fac (n+1) = (n+1) * fac n

Опять же, это соответствует определению, которое они могут найти в учебнике. Невозможно сделать это в SML!

Ответ 1

Как я люблю Haskell, вот причины, по которым я бы предпочел SML для класса в дискретных структурах математики и данных (и большинства других классов новичков):

  • Расходы времени и пространства для программ Haskell могут быть очень трудно предсказать, даже для экспертов. SML предлагает гораздо более ограниченные способы взорвать машину.

  • Синтаксис для функции defintion в интерактивном интерпретаторе идентичен синтаксису, используемому в файле, поэтому вы можете вырезать и вставлять.

  • Хотя перегрузка оператора в SML полностью фиктивная, она также проста. Трудно будет преподавать целый класс в Haskell без необходимости посещать классы типов.

  • Студент может отлаживать с помощью print. (Хотя, как отмечает комментатор, в Haskell можно получить почти такой же эффект, используя Debug.Trace.trace.)

  • Бесконечные структуры данных взрывают умы людей. Для новичков вам лучше назначить тип потока с ref-ячейками и thunks, чтобы они знали, как это работает:

    datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
                               | VALUE of 'a
    type 'a thunk = 'a thunk_contents ref
    val delay : (unit -> 'a) -> 'a thunk
    val force : 'a thunk -> 'a
    

    Теперь это уже не волшебство, и вы можете перейти отсюда к потокам (бесконечные списки).

  • Макет не так прост, как в Python, и может быть запутанным.

Есть два места, в которых у Haskell есть ребро:

  • В ядре Haskell вы можете написать подпись типа функции непосредственно перед ее определением. Это очень полезно для студентов и других начинающих. Там просто не очень хорошо справиться с типом подписей в SML.

  • Haskell имеет более конкретный синтаксис. Синтаксис Haskell является основным улучшением по сравнению с синтаксисом ML. Я написал короткую записку о том, когда использовать круглые скобки в программе ML; это немного помогает.

Наконец, есть меч, который разрезает оба пути:

  • Код Haskell по умолчанию чист, поэтому ваши ученики вряд ли случайно наткнутся на нечистые конструкции (монашеская монада, государственная монада). Но, тем не менее, они не могут печатать, и если вы хотите делать I/O, то в minumum вам нужно объяснить нотацию do, а return запутать.

По теме, вот несколько советов для подготовки курса: не забывайте чисто функциональные структуры данных от Криса Окасаки. Даже если вы не используете своих учеников, вы обязательно захотите иметь копию.

Ответ 2

Мы преподаем Haskell в первые годы в нашем университете. Мои чувства по этому поводу немного смешаны. С одной стороны, преподавание Haskell в первые годы означает, что им не нужно отучивать императивный стиль. Haskell также может создавать очень сжатый код, который могут оценить люди, у которых была какая-то Java.

Некоторые проблемы, которые я заметил, часто у студентов:

  • Совпадение шаблонов может быть немного сложным. Сначала у студентов возникли проблемы с тем, как связаны построение ценности и соответствие шаблонов. У них также были некоторые проблемы, различающие абстракции. Наши упражнения включали функции написания, упрощающие арифметическое выражение, а некоторые ученики с трудом видели разницу между абстрактным представлением (например, Const 1) и представлением метаязыков (1).

    Кроме того, если ваши ученики должны сами писать функции обработки списков, будьте осторожны, указав разницу между шаблонами

    []
    [x]
    (x:xs)
    [x:xs]
    

    В зависимости от того, сколько функционального программирования вы хотите научить их на этом пути, вы можете просто предоставить им несколько функций библиотеки и позволить им играть с этим.

  • Мы не учили наших учеников анонимным функциям, мы просто рассказали им о предложениях where. Для некоторых задач это было немного многословным, но в противном случае сработало. Мы также не говорили им о частичных заявлениях; это, вероятно, довольно легко объяснить в Haskell (из-за формы его написания), поэтому, возможно, стоит их показать.

  • Они быстро обнаружили списки и предпочли их над более высокими функциями порядка filter, map, zipWith.

  • Я думаю, что мы немного упустили учение о том, как позволить им вести свои мысли по типам. Я не совсем уверен, что это полезно для новичков или нет.

  • Сообщения об ошибках обычно не очень полезны для новичков, иногда им может понадобиться помощь. Я сам не пробовал, но есть компилятор Haskell, специально предназначенный для новичков, главным образом с помощью улучшенных сообщений об ошибках: Helium

  • Для небольших программ такие вещи, как возможные утечки пространства, не были проблемой.

В целом, Haskell - хороший учебный язык, но есть несколько подводных камней. Учитывая, что студенты чувствуют себя намного более комфортно с пониманием списков, чем функции более высокого порядка, это может быть аргументом, который вам нужен. Я не знаю, как долго ваш курс или сколько программ вы хотите учить, но планируйте некоторое время для обучения их базовым концепциям - они понадобятся.

Ответ 3

BTW,

# SML имеет действительно интерактивную интерпретатор, в котором функции могут быть как определены, так и использованы. В Haskell, функции должны быть определены в отдельный файл и скомпилирован используется в интерактивной оболочке.

Неточно. Использовать GHCi:

Prelude> let f x = x ^ 2
Prelude> f 7
49
Prelude> f 2
4

Есть также хорошие ресурсы для Haskell в образовании на haskell.org edu. страницы, с опытом от разных учителей. http://haskell.org/haskellwiki/Haskell_in_education

Наконец, вы сможете учить их multicore parallelism просто для удовольствия, если вы используете Haskell: -)

Ответ 4

Многие университеты учат Haskell в качестве первого функционального языка или даже первого языка программирования, поэтому я не думаю, что это будет проблемой.

Проведя некоторые преподавания на одном из таких курсов, я не согласен с тем, что возможные путаницы, которые вы идентифицируете, являются вероятными. Наиболее вероятными источниками ранней путаницы являются ошибки синтаксического анализа, вызванные неправильной компоновкой, и таинственные сообщения о типах классов, когда числовые литералы используются неправильно.

Я также не согласен с предложением, что Haskell не рекомендуется начинающим начинающим с FP. Это, безусловно, большой взрыв подход в том, что строгие языки с мутацией нет, но я думаю, что очень действительный подход.

Ответ 5

  • SML имеет действительно интерактивный интерпретатор, в котором функции могут быть определены и использованы. В Haskell функции должны быть определены в отдельном файле и скомпилированы перед использованием в интерактивной оболочке.

Хотя у Hugs может быть такое ограничение, GHCi не делает:

$ ghci
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> let hello name = "Hello, " ++ name
Prelude> hello "Barry"
"Hello, Barry"

Есть много причин, по которым я предпочитаю GHC (i) над Hugs, это только один из них.

  • SML дает явное подтверждение аргументов функции и возвращаемых типов в синтаксисе, который легко понять. Например: val foo = fn: int * int → int. Синтаксис неявного каркаса Haskell немного тупые, но не совсем чужды. Например: foo:: Int → Int → Int.

SML имеет то, что вы называете синтаксисом неявного карри.

$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- fun add x y = x + y;
val add = fn : int -> int -> int

По существу, SML и Haskell примерно эквивалентны. Я склоняюсь к Haskell, потому что я люблю списки и бесконечные списки в Haskell. Но я обеспокоен тем, что обширное количество символов в компактном синтаксисе Haskell может вызвать проблемы со студентами. Из того, что я собрал, читал другие сообщения на SO, Haskell не рекомендуется начинающим начинающим с FP. Но мы не собираемся создавать полноценные приложения, просто пытаемся простыми алгоритмами.

Мне нравится использовать Haskell гораздо больше, чем SML, но я бы все же преподавал SML.

  • Вторичные мысли nominolo, понимание списка, похоже, мешает учащимся перейти к некоторым более высоким функциям.
  • Если вам нужны лени и бесконечные списки, поучительно реализовать это явно.
  • Поскольку SML с нетерпением оценивается, модель исполнения намного легче понять, а "отладка через printf" работает намного лучше, чем в Haskell.
  • Система типа SML также проще. В то время как ваш класс, вероятно, не будет их использовать, в любом случае, классные классы Haskell по-прежнему являются дополнительным ударом, позволяющим понять, что разница между 'a и ''a в SML достаточно жесткая.

Ответ 6

Большинство ответов были техническими, но я думаю, вы должны рассмотреть хотя бы один, который не является: Haskell (как OCaml), в настоящее время, имеет большее сообщество, использующее его в более широком диапазоне контекстов. Там также имеется большая база данных библиотек и приложений, написанная для получения прибыли и удовольствия в Hackage. Это может быть важным фактором в том, чтобы некоторые из ваших учеников использовали язык после окончания курса и, возможно, позже попробовали другие функциональные языки (например, Standard ML).

Ответ 7

Я удивлен, что вы не рассматриваете OCaml и F #, учитывая, что они затрагивают многие ваши проблемы. Разумеется, достойные и полезные среды разработки являются первоочередной задачей для учащихся? SML отстает, и F # опережает все остальные FPL в этом отношении.

Кроме того, как OCaml, так и F # содержат списки.

Ответ 8

Haskell. Я впереди в своем классе algos/theory в CS из-за того, что я узнал от использования Haskell. Это такой всеобъемлющий язык, и он научит вас тонне CS, просто используя его.

Однако SML намного легче изучить. У Haskell есть такие функции, как ленивые оценки и структуры управления, которые делают его намного более мощным, но со стоимостью крутой кривой (иш). SML не имеет такой кривой.

Тем не менее, большая часть Haskell была недоступна из менее научных/математических языков, таких как Ruby, ObjC или Python.