Функция SMLNJ, которая возвращает в виде пары строку в начале списка

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

инструкции следующие ...

numberPrefix: список символов → строка * список символов

Напишите функцию с именем numberPrefix, которая возвращает (в виде пары) строку, представляющую символы цифры в начале списка ввода и оставшиеся символы после этого префикса. Вы можете использовать в своей реализации функции Char.isDigit и String.implode. Например,

  • numberPrefix [#a, # 2, #c, #, #a];

val it = (, [#a, # 2, #c, #, #a): строка * список символов

  • numberPrefix [# 2, # 3, #, #a];

val it = (23, [#, #a]): строка * список символов

Вот мой код пока ...

fun numberPrefix(c:char list):string*char list =
case c of
[] => []
|(first::rest) => if isDigit first
                  then  first::numberPrefix(rest)
                  else  

;

Я предполагаю, что я пытаюсь сначала добавить в отдельный список, если это действительно цифра, как только я достигну члена списка символов, я хотел бы вернуть этот список с помощью String.implode, но я бью головой об идее передачи вспомогательной функции или даже просто использования выражения let. Как я могу создать отдельный список, одновременно отслеживая, где я нахожусь в исходном списке, чтобы я мог вернуть результат в правильном формате?


person mgherghi    schedule 13.07.2020    source источник


Ответы (1)


Прежде всего, функция должна генерировать пару, а не список.
Базовый случай должен быть ("", []), а не [], и вы не можете передавать рекурсивный результат в нетронутом виде.
(Можно довольно много скажите это только по типам. Обратите внимание на типы; они хотят вам помочь.)

Если вы привяжете результат рекурсии к let, вы можете получить доступ к его частям по отдельности и переставить их.
Прямо рекурсивный дубль может выглядеть так:

fun numberPrefix [] = ("", [])
  | numberPrefix (cs as (x::xs)) = 
        if Char.isDigit x
        then let val (number, rest) = numberPrefix xs 
             in
                 ((str x) ^ number, rest)
             end
        else ("", cs);

Однако разделение списка на два на основе предиката - назовем его splitOn с типом ('a -> bool) -> 'a list -> 'a list * 'a list - является достаточно полезной операцией, и если бы у вас была эта функция, вам понадобилось бы только что-то вроде этого:

fun numberPrefix xs = let val (nums, notnums) = splitOn Char.isDigit xs
                      in
                          (String.implode nums, notnums)
                      end;

(Разделение слева в качестве упражнения. Я подозреваю, что вы уже реализовали эту функцию разделения или ее близкие родственники takeWhile и dropWhile.)

person molbdnilo    schedule 14.07.2020