Начало работы со стандартным 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. Тем не менее, среда выполнения (SML/NJ) будет принимать это значение только для функций, которые принимают только элемент списка в качестве параметра. Но как мне узнать, какие элементы вернуться, если я могу работать только с одним из двух списков?

Я отчаянно нуждаюсь в ресурсе, который переходил бы на подобные вещи, желательно с большими дружескими буквами и множеством примеров кода:/

Ответ 3

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

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

Ответ 4

Рекурсия по нескольким отдельным спискам беспорядочна (но может быть то, что требуется для этого упражнения, конечно) - обычно проще сделать из них один список ( "бок о бок" ), поэтому в вашем случае каждая запись будет иметь пару целых чисел), а затем отобразить или свернуть. Я подозреваю, что у ML будет функция, называемая "zip", которая должна вас запустить.

Кроме того, не совсем то, что вы ищете в данный момент, но если вам нужна хорошая книга ML (это на самом деле диалект OCaml, но достаточно старый, чтобы не отличаться от SML), посмотрите на Cousineau + Mauny, Может быть, если у вас есть время в праздники. Это действительно хорошая книга - немного похоже на SICP, но для ML.

Ответ 5

Вы понимаете, что такое Currying?

Например, вы понимаете разницу между

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) ;

делает?

Currying НЕ НЕОБХОДИМО для решения вашей проблемы, но это метод, который много используется в функциональном программировании. В частности, это дает вам возможность использовать List.map, если хотите. Здесь вы хотите отобразить список1, но функция, которую вы хотите использовать, должна знать о списке2 и результате вычисления. Это говорит о том, что ваш код может иметь форму

List.map (f [] list2) list1

где f - некоторая соответствующая определенная функция Curried. В общем, это полезный трюк для предоставления дополнительной информации функции, которая должна быть функцией "один аргумент" для причин List.map.

Помогает ли это?

Ответ 6

Рассмотрим следующий код отображения 2, эта функция делает именно то, что карта делает, но с двумя списками.

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