我正在尝试在SML中编写一个函数,该函数接收一个int列表并输出一组有序的整数。有序对first int是输入列表中出现的int,有序对中的第二个int是它在输入列表中出现的次数。返回的列表也应按照有序对中的第一个int按升序排列。
例如,输入列表[1, 1, 1, 2, 3, 3, 5]
将输出为[(1,3), (2, 1), (3, 2), (5, 1)]
。
到目前为止,我有一个使用foldl
更新自原始帖子以来的代码。
fun turnIntoPairs l = foldl (fn (e, a) => if List.exists (fn (x, _) => x = e) a then x + 1 else a @ [(e, 1)]) [] l;
我无法更新列表,在那里我找到已经在列表中的有序对 - 我想在序列对中的第二个int中添加一个,当它仍然在列表中时。
非常感谢任何帮助!
C:\Program Files (x86)\SMLNJ\\bin\.run\run.x86-win32.exe: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
[autoloading done]
C:\Users\Localadmin\Desktop\CS 671\Program 3\commonFactors.sml:1.87 Error: unbound variable or constructor: x
C:\Users\Localadmin\Desktop\CS 671\Program 3\commonFactors.sml:1.44-1.110 Error: types of if branches do not agree [literal]
then branch: int
else branch: (''Z * int) list
in expression:
if (List.exists (fn <pat> => <exp>)) a
then <errorvar> + 1
else a @ (e,1) :: nil
[Finished in 0.5s with exit code 1]
答案 0 :(得分:1)
不确定如何修复当前程序,但是你可以通过将它分成两部分来解决这个问题:对相等元素进行分组然后对列表进行排序。
(* Groups successive equal elements into a tuples (value, count) *)
fun group (l as (x :: _)) =
let val (firstGroup, rest) = List.partition (fn y => x = y) l
in
(x, List.length firstGroup) :: (group rest)
end
| group [] = []
(* Now that we have our elements grouped, what's left is to order
them as required. *)
fun turnIntoPairs xs =
ListMergeSort.sort (fn ((x, _), (y, _)) => x >= y) (group xs)
答案 1 :(得分:1)
让我们看看你传递给foldl
的函数:
(fn (e, a) => if List.exists (fn (x, _) => x = e) a then x + 1 else a @ [(e, 1)])
第一个问题(类型检查器正在抱怨)是您的if
表达式返回x + 1
或a @ [(e, 1)]
,这似乎有问题,因为前者是类型int
的值,后者属于(int * int) list
类型。
让我们使用一些我不会定义的辅助函数重写你的代码,看看它是否变得更清晰:
(fn (e, a) => if List.exists (fn (x, _) => x = e) a then increment a e else a @ [(e, 1)])
increment
的类型为(int * int) list -> int -> (int * int) list
。
您可以实施increment
吗?
答案 2 :(得分:0)
和Gian一样,我更愿意把它分成两个函数:一个折叠,一个辅助函数插入。顺便说一下,insert函数会将一个元素和一个现有的(int * int) list
作为累加器函数来接受这两个参数。
通常情况下,我会写一个curried的插入函数(即insert x xs
),但是如果我把它写得不合理(即insert (x, xs)
),我可以将它直接传递给foldl
:
fun insert (x, []) = [(x,1)]
| insert (x, ((y,c)::xs)) =
if x = y then (y,c+1)::xs else (y,c)::insert (x, xs)
fun turnIntoPairs xs = foldl insert [] xs