Прежде всего я бы начал использовать сопоставление с образцом в определении функции
вместо того, чтобы иметь "верхний уровень" оператора case. Его в основном сводится к
то же самое после удаления сахара. Также я бы избавился от явных аннотаций типов, если в этом нет особой необходимости:
fun all_except_option (str, []) = NONE
| all_except_option (str, x :: xs) =
case same_string(x, str) of
true => SOME xs
| false => case all_except_option(str, xs) of
NONE => NONE
| SOME y => SOME (x::y)
fun get_substitutions1 ([], s) = []
| get_substitutions1 (x :: xs, s) =
case all_except_option(s, x) of
NONE => get_substitutions1(xs, s)
| SOME y => y @ get_substitutions1(xs, s)
Если скорость не важна, вы можете объединить два случая в первой функции:
fun all_except_option (str, []) = NONE
| all_except_option (str, x :: xs) =
case (same_string(x, str), all_except_option(str, xs)) of
(true, _) => SOME xs
| (false, NONE) => NONE
| (false, SOME y) => SOME (x::y)
Но так как вы используете append (@), во второй функции, и так как она не
хвост рекурсивный, я не верю, что это твоя главная проблема. Имейте в виду, что
append является потенциальным «злом», и вы почти всегда должны использовать конкатенацию (и
затем верните свой результат при возврате) и рекурсию хвоста, когда это возможно
всегда есть).
Если вам действительно нравятся аннотации явного типа, то вы можете сделать это так:
val rec all_except_option : string * string list -> string list option =
fn (str, []) => NONE
| (str, x :: xs) =>
case (same_string(x, str), all_except_option(str, xs)) of
(true, _) => SOME xs
| (false, NONE) => NONE
| (false, SOME y) => SOME (x::y)
val rec get_substitutions1 : string list list * string -> string list =
fn ([], s) => []
| (x :: xs, s) =>
case all_except_option(s, x) of
NONE => get_substitutions1(xs, s)
| SOME y => y @ get_substitutions1(xs, s)
Но это только мой предпочтительный способ, если мне действительно нужно добавить аннотации типов.
Кстати, с какой стати у вас есть функция same_string
? Вы можете просто сделать сравнение напрямую вместо этого. Использование вспомогательной функции просто странно, если вы не планируете в какой-то момент заменить ее какой-то специальной логикой. Однако названия ваших функций этого не говорят.