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.