Эта стандартная функция ML дает мне «необработанное исключение: Match».Может ли кто-нибудь указать мне правильное направление для решения проблемы? - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь написать стандартную функцию ML под названием «select», которая получает список целых чисел и функцию.Переданная функция получает целое число и возвращает логическое значение (например, fun isOdd 3 -> true).Функция состоит в том, чтобы просмотреть каждое целое число в списке и добавить их в новый список, если данная функция возвращает true для этого целого числа.Так что select [1,2,3,4,5] isOdd вернет [1,3,5].Вот код, который я получил:

fun select (l : int list, f:int -> bool) = 
    let val newlist : int list = []
        fun recurse (x::xs) =
            if f(x)
                then newlist :: [x] :: recurse(xs)
            else
                newlist :: recurse(xs)
    in
        recurse(l : int list)
    end

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Продолжая переписывать molbdnilo на select, кроме удаления ограничений типов, наличие внутренней функции для рекурсии также не требуется, так как сам select может быть легко рекурсивным:

fun select ([], f) = []
  | select (x::xs, f) =
    if f x
    then x :: select (xs, f)
    else select (xs, f)
0 голосов
/ 22 сентября 2018

recurse не имеет регистра для пустого списка, поэтому произойдет сбой при достижении пустого списка.

Давайте исправим это:

fun select (l : int list, f:int -> bool) = 
    let val newlist : int list = []
        fun recurse [] = []
          | recurse (x::xs) =
            if f(x)
                then newlist :: [x] :: recurse(xs)
            else
                newlist :: recurse(xs)
    in
        recurse l
    end

и протестируем:

- select ([1,2,3,4], fn x => x mod 2 <> 0);
val it = [[],[1],[],[],[3],[]] : int list list
- select ([1], fn x => true);
val it = [[],[1]] : int list list
- select ([1], fn x => false);
val it = [[]] : int list list

Это не хорошо - мы хотим [1,3], [1] и [].

Тип вашей функции:

val select = fn : int list * (int -> bool) -> int list list

Результат int list list неверен;это должно быть int list.
Это происходит потому, что первый элемент результата из recurse является int list - пустым newlist - поэтому результат должен быть int list list.

Исправление проблемы дает

fun select (l : int list, f:int -> bool) = 
    let fun recurse [] = []
          | recurse (x::xs) =
            if f x
            then x :: recurse xs
            else recurse xs 
    in
        recurse l
    end

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

...