子句的右侧与函数结果类型不一致

right-hand-side of clause doesn't agree with function result type

写一个函数remove_option,接受一个字符串和一个字符串列表。 Return NONE 如果字符串不在列表中,否则 return SOME xs 其中 xs 与参数列表相同,只是字符串不在其中。您可以假设该字符串最多出现在列表中一次。使用提供给您的 same_string 来比较字符串。示例解决方案大约有 8 行。

函数类型应该是 fn : string * string list -> string list option.Here 是我的代码

fun same_string(s1 : string, s2 : string) =
    s1 = s2
fun remove_option (str: string ,str_list : string list) =
    case str_list of 
        [] => NONE
          | x::xs => if same_string(x,str) 
             then SOME xs 
             else x :: remove_option( str,xs)

和错误报告

hw2provided.sml:10.5-15.37 Error: right-hand-side of clause doesn't agree with f
unction result type [tycon mismatch]
  expression:  _ option
  result type:  string list
  in declaration:
    remove_option =
      (fn (<pat> : string,<pat> : string list) =>
            (case str_list
              of <pat> => <exp>
               | <pat> => <exp>))

uncaught exception Error
  raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:292.17-292.20

那么错误在哪里?

问题是你想 return 一个 string list option 但行

else x :: remove_option( str,xs)

看起来你想要return一个string list

你需要用remove_option( str,xs)的return值做的是

1) 如果是NONE

,决定怎么办

2) 提取字符串列表 strings(或任何你想称呼它的东西)如果它的形式是 SOME strings,将 x 添加到列表的前面,并在 return 之前用 SOME 重新打包它。

您似乎对 case 的使用感到满意,因此您可以在此处使用它。

由于 John 指出了漏洞所在,这里有一些额外的评论:

  • 由于函数same_string没有被注入,所以是多余的。您不妨使用 =.
  • return'一个选项的递归函数有点棘手,因为您需要解压结果:

    fun remove_option (s1, []) = NONE
      | remove_option (s1, s2::ss) =
        if s1 = s2
        then SOME ss
        else case remove_option (s1, ss) of
                  NONE => NONE
                | SOME ss' => SOME (s2::ss')
    

    一般来说,当你看到模式时

    case x_opt of
         NONE => NONE
       | SOME x => SOME (f x))
    

    这可以重构为使用例如Option.map : ('a -> 'b) -> 'a option -> 'b option:

    Option.map f x_opt
    

    在这种情况下,

    fun curry f x y = f (x, y)
    
    fun remove_option (s1, []) = NONE
      | remove_option (s1, s2::ss) =
        if s1 = s2
        then SOME ss
        else Option.map (curry op:: s2) (remove_option (s1, ss))
    

    其中 curry op:: s2,将 s2 放在列表前面的函数。