在SML中过滤两个列表很困难

时间:2013-02-11 18:28:11

标签: list sml

我试图通过两个列表“加倍”过滤,具体取决于使用HOP进行数据类型测试而不递归。以下是我对解决方案的非常丑陋的尝试......

datatype 'a test = Test of ('a -> bool) * string;

fun foo xs lst = 
    let 
        fun foo_bar(x, ls) =
            let                
                val tests = (List.filter (fn (Test(f, str)) => (f x)) ls)
            in
                (List.map (fn (Test(f, str)) => str) tests)
            end 
    in
        (List.map (fn x => foo_bar(x, lst)) xs)
    end;

allPass: 'a list -> 'a test list -> 'a test list;

allPass [1, 2, 40, 150] [positive, even]应该返回字符串"pos"

目前,我的函数正在返回一个嵌套列表:[["pos"], ["pos even"], ["pos even"], ["pos even"]]。是否有一种非递归的方法从这个结果中提取“pos”,或者我是否会在完全错误的方向上解决这个问题?

1 个答案:

答案 0 :(得分:0)

你正朝着正确的方向前进,但你还没到那里。这就是我想你想要的。

获取值列表和测试列表。返回所有值传递的测试名称列表。

好的,我们需要:

  1. 过滤测试列表。测试的谓词是所有值都必须通过。
  2. 提取传递的测试的名称。
  3. 好的,那么我们如何判断列表中的所有值是否通过一次测试?很简单,我们使用List.all

    List.all    : ('a -> bool) -> 'a list -> bool
    

    我们可以定义一个函数:

    fun allPassesTest xs (Test(f,s)) = List.all f xs
    

    当且仅当xs中的所有值都通过测试时,这将返回true。现在我们根据这个函数过滤测试列表:

    fun allPass xs tests = List.filter allPassesTest xs tests
    

    但是,这会返回'a test list而不是string list,因此您需要提取名称。

    fun name (Test(f,s)) = s
    fun allPass xs tests = map name (List.filter allPassesTest xs tests)