First of all, I would start using pattern matching in a function definition instead of having a top-level operator. It basically comes down to the same item after degreasing. I would also get rid of explicit type annotations, unless this is required:
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)
If speed doesn't matter, you can combine two cases in the first function:
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)
But since you are using append (@) in the second function, and since it is not tail recursive, I do not consider this to be your main concern. Keep in mind that append is a potential “evil” and you should almost always use concatenation (and then reverse your result when it returns) and tail recursion whenever possible (it always is).
If you really like explicit type annotations, you can do it like this:
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)
But this is only my preferred way if I really need to add type annotations.
By the way, why do you have the
same_string function? Instead, you can simply compare it. Using an auxiliary function is simply monstrous if you do not plan to exchange it at some point with some special logic. However, the names of your functions are not so important that.