我如何在ML中使用数据类型列表实现multiFilter

时间:2015-08-29 19:52:40

标签: functional-programming sml ml

datatype 'a Multilist = 
   Node of 'a list
 | List of 'a Multilist list;

fun isGreaterThen x y = y > x;

fun multiFilter  f (List([])) = []  
  | multiFilter  f  (List(m::multil)) = 
    let fun flattenAuxiliray(Node(value)) = 
                   if (f value = true) then (value) else nil
          | flattenAuxiliray((List(nil))) = nil
          | flattenAuxiliray(List(m::mlist1)) = (flattenAuxiliray(m)) @ 
                   (flattenAuxiliray((List(mlist1)))) 
    in (flattenAuxiliray(m)) @ (multiFilter f (List(multil)))
    end;

我在这个输入上收到错误:

val l = List [Node [3,5,18], Node [7]];
multiFilter (isGreaterThen 6) l;

stdIn:7.1-8.46 Error: operator and operand don't agree [tycon mismatch]
  operator domain: ('Z list -> bool) * 'Z list Multilist
  operand:         (int -> bool) * int list Multilist
  in expression:
    multiFilter (isGreaterThen 6,List (Node <exp> :: <exp> :: <exp>))

输出:

val it = [18,7] : int list

2 个答案:

答案 0 :(得分:0)

你的类型错误是说第一个参数需要'Z list -> bool类型的东西,这意味着它是一个接收多态列表并返回bool的函数。但是,您提供的函数需要int并返回bool。相反,它应该包含int的列表并返回bool。您可以通过将isGreaterThan(类型int -> int -> bool)更改为int -> int list -> bool类型来实现此目的,该类型会将列表中的所有内容与第一个参数进行比较,仅当所有元素都较小时才返回true

答案 1 :(得分:0)

你的问题有根源:

flattenAuxiliray(Node(value)) = 
                   if (f value = true) then (value) else nil

您的数据类型为Node of 'a list,因此value必须为'a list 由于您将f应用于valuef必须包含'a list -> bool类型,但您传递的isGreaterThan 6类型为int -> bool

您可能正在寻找filter以删除所有不满足谓词的元素:

flattenAuxiliray (Node value) = 
                   List.filter f value

(旁注:大量的括号和缺少空格使得SML很难阅读。请记住,代码大部分时间都不会写入或执行,而是由人类阅读。)

完成功能:

fun multiFilter  f (List []) = []  
  | multiFilter  f (List (m::multil)) = 
    let fun flattenAuxiliary (Node ls) = List.filter f ls
          | flattenAuxiliary (List []) = []
          | flattenAuxiliary (List (m::mlist1))
            = (flattenAuxiliary m) @ (flattenAuxiliary (List mlist1)) 
    in (flattenAuxiliary m) @ (multiFilter f (List multil))
    end;

相互作用:

- multiFilter (isGreaterThan 6) (List [Node [3,5,18],Node [7]]);
val it = [18,7] : int list