Использование сгиба в SML - PullRequest
       14

Использование сгиба в SML

4 голосов
/ 09 марта 2012

Я сейчас пытаюсь выучить smlnj и у меня возникают проблемы с функцией сгиба.

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

          select (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
          val it = [2,4,6,8,10] : int list

Итак, вот что я имею до сих пор ...

          fun select f l = foldl (fn (x,y) => if (f(x)) then x else 0) 0 l;

Это, очевидно, работает неправильно.Он просто возвращает 10. Я уверен, что мне нужно как-то использовать op ::, чтобы заставить это работать, но я не могу понять это.Я думаю, что это должно выглядеть примерно так ...

          fun select f l = foldl (fn (x,y) => if (f(x)) then op:: else []) [] l;

Но это не работает.Любая помощь будет оценена.Спасибо!

Ответы [ 2 ]

4 голосов
/ 09 марта 2012

Ты рядом. Единственными проблемами являются случаи if / else в функции, которую вы передаете fold.

Помните, в вашем fn (x,y), x - это элемент списка, который вы рассматриваете, а y - это результат сворачивания остальной части списка. Если f(x) терпит неудачу, вы хотите исключить x из результата, поэтому вы просто передаете y. Если f(x) успешно, вы хотите включить x в ваш результат, поэтому вы возвращаете y@[x].

Обратите внимание, что лучше избегать использования оператора добавления (y@[x]), где это возможно, поскольку это операция с линейным временем, в то время как предварительное добавление (x::y) является постоянным. Конечно, замена одного на другой в этом случае создаст ваш список в обратном направлении. Вы также можете обойти это, сложив в обратном направлении, то есть, используя foldr вместо foldl.

2 голосов
/ 09 марта 2012

То, что вы реализуете, уже существует. Это называется filter.

- List.filter (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list

Ваша попытка во втором примере кода довольно близка. Я могу указать на несколько проблем:

  • op:: - это оператор, который является функцией. Вы, вероятно, не хотите возвращать функцию. Вместо этого вы, вероятно, захотите использовать оператор для создания списка из элемента head и остальной части списка, например: x :: y

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

  • Подумайте, будет ли левый или правый сгиб наиболее подходящим для вашей продукции

...