SML 列表选项回避;如何使用递归输出 SOME 列表

SML list option recusion; how to use recursion to output a SOME list

目前,我的代码接受一个字符串 s 和一个字符串列表 sl 和 returns 一个字符串列表,其中 s 被删除(一次)

fun all_except_option (s, sl) =
    case sl of
    [] => []
      | hd::tl = if same_string(s, hd)
          then tl
          else hd::all_except_option(s, tl) 

但是,我想要的是 return NONE 如果字符串 s 不在列表中,如果在列表中,则 return SOME (当前函数的输出)。但是,我不能简单地在 hd::all_except_option(s, tl) 之前添加 SOME(,因为 hd 将附加到输出选项的内容,我不知道该怎么做。

编辑:谢谢大家!

听起来你需要一个新功能:

fun some_option(s,sl) = SOME( all_except_option(s, sl) )

嗯,不完全是这样,因为它不处理 all_except_option returns [] 的情况,但我会把它留作练习。

您可以使用

case all_except_option(s, tl) of ...

匹配两种不同的情况并以适当的方式处理每一种情况。

fun all_except_option (s, ss) =
    case ss of
      [] => NONE
    | s'::ss' =>
        if s = s' then SOME ss' else
        case all_except_option (s, ss') of
          NONE => NONE
        | SOME ss'' => SOME (s'::ss')

请注意,这只会删除第一次出现的 s,它反映了您的版本。

您也可以使用 Option.map 来避免嵌套:

fun all_except_option (s, ss) =
    case ss of
      [] => NONE
    | s'::ss' =>
        if s = s' then SOME ss'
        else Option.map (fn ss' => s'::ss') (all_except_option (s, ss'))

Andreas Rossberg 提供了两个完整的示例。

这里是模式匹配在函数参数中的变体:

fun curry f x y = f (x, y)

fun all_except_option (s, []) = NONE
  | all_except_option (s, t::ts) =
      if s = t
      then SOME ts
      else Option.map (curry op:: t) (all_except_option (s, ts))

其中 curry op:: t 是接受列表并将 t 放在它前面的函数:

- curry op:: "x" ["y", "z"];
> val it = ["x", "y", "z"] : string list

等价于 fn ss' => t::ss'.

如果你像我一样苦苦挣扎,花了太多时间来解决课程中的那个问题,这里有一个你可以简单理解的解决方案:

(* string * string list -> string list option *)
(* Eliminate a specific string from a list of string*)
(* fun all_except_option (s, los) = [] *) (* stub *)
fun all_except_option (exc, los) =
    let
         fun all_except_option_acc (los, acc, f) = 
               case los of
                  [] => if f
                            then SOME acc
                            else NONE
               |  s::los' =>  if same_string (s, exc)
                                 then all_except_option_acc(los', acc,    true)
                                 else all_except_option_acc(los', s::acc, f)
    in
        all_except_option_acc(los,[], false)
    end