1

我需要编写一个函数来回答这些规范:

clean_list( [],s1] = NONE

clean_list( xs, "") = NONE

clean_list ([s1, s1, s1, s1], s1) = NONE

clean_list([s1, s2, s3, s2, s1], s3) = [s1, s2, s2, s1]

其中s1, s2,s3是一些字符串和xs字符串列表。

我可以使用两个辅助函数来做到这一点is_into(xs: string list, s1: string) -> boolremove(xs: string list, s1: string) -> string list但是通过列表递归两次似乎很难看。

clean_list(xs: string list, s1: string) =
    case (xs, s1) of
         ( [], _ ) => NONE
        |( _, "" ) => NONE
        |( _, _) => if is_into(xs, s1)
                    then remove(xs, s1)
                    else NONE

有没有办法做到这一点,而无需在列表中递归两次(一次is_into和一次remove)?

注意:不要使用任何内置函数。

抱歉,我忘记了规格中的一个重要案例

clean_list ([s1, s2, s3, s4], s10] = NONE
4

2 回答 2

1

您的clean_list函数不会进行类型检查,因为某些分支具有 type'a option而其他分支具有 type 'b list

假设你想退货'b listNONE应该换成[]。您可以递归地使用模式匹配clean_list来避免需要辅助函数:

fun clean_list(xs: string list, s1: string) =
    case (xs, s1) of
      ([], _) => []
    | (_, "") => []
    | (x::xs', _) => if x = s1 
                     then clean_list(xs', s1)
                     else x::clean_list(xs', s1)
于 2013-01-23T18:48:30.977 回答
1

您可以轻松地遍历列表一次,逐个元素并删除与给定字符串匹配的所有内容,最后返回结果列表SOME lst在哪里lst

fun clean_list ([], _ ) = NONE
  | clean_list (_, "") = NONE
  | clean_list (xs, str) =
    let
      fun clean_list' [] = []
        | clean_list' (x::xs) =
          if x = str then
            clean_list' xs
          else
            x :: clean_list' xs
    in
      SOME (clean_list' xs)
    end

更新

我注意到上面的代码实际上并没有处理这种情况:clean_list ([s1, s1, s1, s1], s1) = NONE. 但是,这是一个简单的解决方法。

我可以看到,鉴于您的新更新规范,如果该元素首先不在列表中,则NONE应该返回。这就像说,如果在遍历所有元素时没有删除任何元素,则 return NONE

希望您可以看到,这可以通过向辅助函数添加一个额外的布尔参数来实现,最初将其设置为 false,然后在每次递归调用中传递其值,除非删除元素,这里可以始终设置为 true。

然后可以使用它来确定返回的天气,结果列表SOME lst在哪里,或者是否没有删除任何元素。lstNONE

考虑到这两件事,需要修复,让辅助函数在累积参数中建立其结果可能是一个好主意。这样您就可以完全控制,并且可以NONE在最后累加列表为空时轻松返回。

于 2013-01-23T18:51:05.363 回答