Начало работы со 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 ответов

Решение

Программирование в 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

Другие вопросы по тегам