带折叠的多种输入类型

Multiple input types with fold

我想弄清楚如何在不同类型的输入上实现折叠功能。作为示例,我将对列表使用计数函数(不过,我有多个函数可以为此实现)。 假设一个 int 列表输入(尽管这应该适用于任何类型的列表),我的计数函数将是

val count = foldr (fn(x:int,y)=>y+1) 0 ;
val count = fn : int list -> int

但是,我正在尝试创建类型为

的计数函数
val count = fn : int list * bool list -> int

其中int列表是集合的全域,bool决定全域的哪些值在集合中。即,(1,3,5,6),(true,false,false,true) 结果是最后一组 (1,6),其计数为 2。我首先想到的是某种形式

val count= foldr (fn(x:(int*bool),y)=>if #2x then y+1 else y ) 0 ;

但这会导致 return 类型的

val count = fn : (int * bool) list -> int

这不是我需要的。从逻辑上讲,它们是相似的,但我希望将这两种类型分别组合在一个列表中。

  1. 您可以使用 ListPair.foldl:

    fun count (xs, bs) = ListPair.foldl (fn (x, b, acc) => ...) ... (xs, bs)
    

    其中第一个 ...xbacc 的某种组合,第二个 ... 是初始值。

    这假定 xsbs 的长度相同,如果不是,则丢弃较长列表中的剩余元素。 (您可能应该尝试证明在 xsbs 更长的情况下是否给出了正确答案。)

  2. 否则,您需要将 int 列表 × bool 列表 合并(也称为 zip)到 (int × bool) 列表 通过制作一个组合两个列表的函数,并将此函数与您已经在做的折叠结合使用。

    fun combine (x::xs, y::ys) = ...
      | combine (..., ...) = ...
    

    这个函数可以等效于ListPair.zip.