如何在ML字符串列表中查找出现次数?

时间:2016-12-10 07:10:51

标签: functional-programming sml smlnj ml

我是ML的新手,这是我尝试写一个接收的函数:

  • 字符串列表L
  • string str
  • int counter

该函数应返回str

L的出现次数

这是我的代码:

(* 
 * return number of occurences of str in L
 * count should be initialized to zero. 
 *)
 fun aux_num_of_occur(L: string list) (str:string) (count:int) =
    if null L then 0
    else if str = hd(L) then
        aux_num_of_occur tl(L) str (count+1)
    else
        aux_num_of_occur tl(L) str count

这些是我得到的错误:

Error: case object and rules don't agree [tycon mismatch]
  rule domain: string list * string * int
  object: ('Z list -> 'Z list) * 'Y * 'X
  in expression:
    (case (arg,arg,arg)
      of (L : string list,str : string,count : int) =>
           if null L
           then 0
           else if <exp> = <exp> then <exp> <exp> else <exp> <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:296.17-296.20

我的问题:

  1. 语法有什么问题?
  2. 我不清楚错误信息是什么:什么是 在这种情况下ruleobject
  3. 如何通过递归调用函数返回int?是通过传递counter作为参数吗?

1 个答案:

答案 0 :(得分:4)

这是一个经典的错误:tl(L)tl L是相同的 - 你不需要在类似ML的语言中使用括号进行函数应用,你只需并置函数和参数(一个或多个)。

因此aux_num_of_occur tl(L) ...aux_num_of_occur tl L ...相同,即您尝试将aux_num_of_occur应用于tl函数,而不是字符串列表。现在,tl函数的类型为'a list -> 'a list,这是您在错误消息中看到的内容(其中'a'Z)。

我应该说,这些nullhdtl函数的样式在SML中并不是非常惯用 - 你可以使用pattern-mathing代替。使aux_num_of_occur本地化以防止名称空间污染,防止错误使用(您控制count的初始值)也更方便。此外,这为您提供了在进一步递归时不会一直传递str的优势。

fun num_of_occur ss str =
  let
      fun loop [] count = count
        | loop (s::ss) count =
            if s = str
            then loop ss (count + 1)
            else loop ss count
  in
      loop ss 0
  end

请注意,num_of_occur具有更通用的类型''a list -> ''a -> int,其中''a表示具有相等性比较的任何类型。编译器将生成警告

  

警告:调用polyEqual

您可以忽略或向num_of_occur添加一些类型注释。有关详细信息,请参阅here