条款的右侧与功能结果类型不一致

时间:2016-04-25 12:16:57

标签: sml smlnj

编写一个函数remove_option,它接受一个字符串和一个字符串列表。如果字符串不在列表中,则返回NONE,否则返回SOME xs,其中xs与参数列表相同,但字符串不在其中。您可以假设字符串最多只在列表中一次。使用提供给您的same_string来比较字符串。样品溶液约为8行。

函数类型应为fn:string * string list - >字符串列表选项。这是我的代码

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

那么bug在哪里?

2 个答案:

答案 0 :(得分:5)

问题是您要返回string list option但行

else x :: remove_option( str,xs)

似乎要返回string list

您需要对remove_option( str,xs)的返回值执行

1)决定如果是NONE

该怎么做

2)提取字符串列表strings(或任何你想要称之为的内容),如果它的格式为SOME strings,将x添加到列表的前面,并重新打包在返回之前使用SOME

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

答案 1 :(得分:3)

由于约翰显示了错误的位置,这里有一些额外的评论:

  • 由于未注入函数same_string,因此它是多余的。您也可以使用=
  • 返回'一个选项的递归函数有点棘手,因为你需要解压缩结果:

    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放在列表前面的函数。