2015-08-29 5 views
-1
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; 

Я получаю ошибку на входе:как я могу реализую комбифильтр со списком типов данных в ML

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 

ответ

0

Ваша ошибка типа говорит, что первый параметр ожидает что-то типа 'Z list -> bool, то есть это функция, которая принимает полиморфный список и возвращает bool. Однако вы выполняете функцию, которая принимает int и возвращает bool. Вместо этого он должен взять в списке int s и вернуть bool. Вы можете добиться этого, изменив isGreaterThan (типа int -> int -> bool) на что-то типа int -> int list -> bool, которое будет сравнивать все в списке с первым параметром, возвращая true только тогда, когда все элементы будут меньше.

+0

Я не могу изменить isGreaterThan и тип данных – alex

0

Ваша проблема имеет свои корни здесь:

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

Ваш тип данных говорит Node of 'a list так value должны быть 'a list.
Поскольку вы применяете f к value, f должен иметь тип '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 
+0

мне нужно передать список только один раз. – alex

+0

@alex Я не понимаю. – molbdnilo

+0

Я могу перебирать список только один раз. Мой начальный список - List [Node [3,5,18], Node [7]] – alex