Sml 条款的右侧没有';不符合函数结果类型

Sml 条款的右侧没有';不符合函数结果类型,sml,smlnj,Sml,Smlnj,编写一个函数remove_option,它接受一个字符串和一个字符串列表。如果字符串为空,则返回NONE 不在列表中,否则返回一些xs,其中xs与参数列表相同,但字符串不在其中 在里面。您可以假定该字符串最多在列表中出现一次。使用提供给您的相同_字符串 比较字符串。样品溶液约为8行 函数类型应该是fn:string*string list->string list选项。这是我的代码 fun same_string(s1 : string, s2 : string) = s1 = s2 f

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

函数类型应该是fn:string*string list->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
HW2已提供。sml:10.5-15.37错误:条款右侧与f不一致
函数结果类型[tycon不匹配]
表达式:\选项
结果类型:字符串列表
在声明中:
删除\u选项=
(fn(:字符串,:字符串列表)=>
(案例列表)
of=>
|  => ))
未捕获异常错误
在以下位置引发:../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在哪里呢?

问题是您想要返回一个
字符串列表选项,但是行

else x :: remove_option( str,xs)
使其看起来像是要返回一个
字符串列表

对于
remove_选项(str,xs)
的返回值,您需要做的是

1) 决定如果是
NONE

2) 提取字符串列表
strings
(或任何你想叫它的名称),如果它的形式是
SOME strings
,将
x
钉在列表的前面,并在返回之前用
SOME
重新打包


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

既然John指出了错误所在,下面是一些额外的注释:

  • 由于没有注入函数
    相同的\u字符串
    ,因此它是多余的。您不妨使用
    =
  • 返回“选项”的递归函数有点棘手,因为您需要解压缩结果:

    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
    置于列表前面的函数


你说的“注射”是什么意思?基于代码片段,我有点直觉地理解了它,但这里似乎有更技术的含义。它可能只是你认为它的意思。如果
remove\u option
将函数
string*string->bool
作为参数,那么'a不需要是一个相等类型。哦,好的,所以它作为参数传入。谢谢我以为你的意思与这里的注入类似:@IonuțG.Stan:不,但是谢谢你的链接,这是一本有趣的书。本周末我想到了一个类似的引用示例:
纠缠:'a->(unit->'a)*('a->unit)
。我不确定这是一个好的模式,但它似乎很有趣。@Slark on StackOverflow,习惯上会将其中一个答案标记为已接受。在upvote和downvote按钮下方有一个小勾号。使用该选项将答案标记为已接受。