Начало работы со Standard ML
Я ищу какое-то руководство по "ML для начинающих" - пока Google привел меня к некоторым неясным спискам рассылки или текстам над головой.
Проблема в том, что у меня пока нет опыта в функциональном программировании, и обдумать концепции оказалось гораздо сложнее, чем ожидалось. Например, задача, которую я сейчас пытаюсь выполнить (да, университет:)), состоит в том, чтобы сопоставить два списка (a,b) и (c,d), так что в результате получается список (a,d) из пар, где b = c.
Что я обычно делал бы, это:
result = []
for each x in list1 do
for each y in list2 do
if x.b == y.c result.add (x.a, y.d)
end
end
Но я даже не могу начать реализовывать что-то подобное в SML. Например, я знаю, что мог бы перебирать списки с вложенными map f list
"S. Однако среда выполнения (SML/NJ) примет это только для функций, которые принимают в качестве параметра только элемент списка. Но как мне узнать, какие элементы вернуть, если я могу работать только с одним из двух списков одновременно?
Я отчаянно нуждаюсь в ресурсе, который бы разбирался с такими вещами, желательно с большими дружескими буквами и множеством примеров кода:/
6 ответов
У меня есть некоторые ресурсы SML, отмеченные закладкой:
Программирование в стандарте ML '97: интерактивное учебное пособие
Элементарный Стандарт ML (Amazon Kindle)
Элементы программирования ML (amazon.com)
Программирование в Standard ML профессором Робертом Харпером из CMU
Для упражнения, которое вы упоминаете, подумайте о функции add
который возвращает новый список вместо изменения существующего, и подумайте, как бы вы рекурсивно реализовали упражнение на вашем любимом языке высокого уровня, это будет первым шагом.
Вам не нужно использовать map
или любая другая существующая функция ML высшего порядка! Это просто ярлыки для опытных программистов. Используйте только сопоставление с образцом и рекурсию. Но вы можете посмотреть на реализацию функций, таких как map
если вы ищете примеры хорошо используемой рекурсии и сопоставления с образцом.
Повторение в нескольких отдельных списках является грязным (но, разумеется, это может быть необходимо для этого упражнения) - обычно проще составить из них один список ("бок о бок", поэтому в вашем случае каждая запись будет иметь пару целых чисел), а затем отобразить или сложить над этим. Я подозреваю, что у ML будет функция, называемая чем-то вроде "zip", которая должна помочь вам начать.
Кроме того, не совсем то, что вы ищете в данный момент, но если вы хотите хорошую книгу по ML (на самом деле это диалект OCaml, но достаточно старый, чтобы не сильно отличаться от SML), посмотрите на Cousineau + Mauny. Может быть, если у вас есть время в отпуске. Это действительно хорошая книга - немного похожая на SICP, но для ML.
Вы понимаете, что такое карри?
Например, вы понимаете разницу между
fun compute(m,b,x):real = m*x+b ;
а также
fun linearF (m,b) x : real = m*x+b ;
Если вы это сделаете, вы можете объяснить, что
val g = linearF(1.0,~1.0) ;
делает?
Карринг не является строго необходимым для решения вашей проблемы, но это метод, который часто используется в функциональном программировании. В частности, он дает вам возможность использовать List.map, если хотите. Здесь вы хотите отобразить list1, но функция, которую вы хотите использовать, должна знать о list2 и результате вычислений. Это говорит о том, что ваш код может иметь форму
List.map (f [] list2) list1
где f - некоторая правильно определенная функция Curried. В целом, это полезный прием для предоставления дополнительной информации функции, которая должна быть функцией с одним аргументом по причинам, подобным List.map.
Это помогает?
Рассмотрим следующий код map2, эта функция делает именно то, что делает карта, но с двумя списками.
exception UnequalLengths;
fun map2(f,[],[]) = []
| map2(f,(a::s),(a'::s')) =
(f(a,a'))::(map2(f,s,s'))
| map2(f,s,s') = raise UnequalLengths;
fun plus(x,y) = x + y;
fun concat(s1,s2) = s1 ^ s2;
Теперь вы используете это так:
- map2(plus,[1,2,3],[4,5,6]);
val it = [5,7,9] : int list
- map2(concat,["a","b","c"],["d","e","f"]);
val it = ["ad","be","cf"] : string list
Наслаждайтесь XD