2013-03-21 6 views
4

Я хочу написать функцию в Ocaml, которая задала список четверки и четверку (x, y, z, f), возвращает список, содержащий кортежи (x ', y', z ', g) такие, что x = x' или y = y 'или z = z' (это целые числа). Вот моя первая попыткаВложенное совпадение шаблонов в Ocaml

let rec constrained_by c list = 
    match s with 
    | []-> [] 
    | hd :: tl -> 
begin 
    let Cell(x,y,r,_)= c in (*warning*) 
    begin 
    match hd with 
    | Cell(x,_,_,Some(_))-> hd::constrained_by c tl 
    | Cell(_, y, _,Some(_)) -> hd::constrained_by c tl 
    | Cell(_, _, r,Some(_)) -> hd::constrained_by c tl 
    | _ -> constrained_by c tl 
    end 
end 

Проблема: когда он вызывается, он возвращает исходный список, независимо от того, какой четвёрки мы сопоставляем. Кроме того, проблема в том, что он возвращает предупреждение о том, что x, y, r в строке (предупреждение) не используются.

ответ

4

Я думаю, что вы неправильно используете шаблон, соответствующий там. Образец, подобный Cell(x,_,_,Some(_)), будет соответствовать чему угодно, поскольку он переплетается x. Тот факт, что существует переменная x в области видимости, не означает, что она будет настаивать на том, что этот элемент кортежа имеет то же значение, что и x. Ваши три шаблона полностью эквивалентны тому, что они соответствуют в результате.

Возможно, вам понадобится вместо этого использовать защитные приспособления, если это так, как вы хотите достичь своей задачи.

6

Как сказал Джан, охранники - это решение вашей проблемы. Хорошая новость заключается в том, что код может быть ближе к письменной спецификации:

let rec constrained_by ((x,y,z,_) as c) list = match list with 
    | [] -> [] 
    | ((x',y',z',_) as c') :: tl when x = x' or y=y' or z=z' -> 
     c' :: constrained_by c tl 
    | hd :: tl -> constrained_by c tl 
;; 

Крошка тест:

let _ = constrained_by (1,2,3,"foo") [1,0,0,0; 0,2,0,0; 0,0,3,0; 0,0,0,0];; 
- : (int * int * int * int) list = [(1, 0, 0, 0); (0, 2, 0, 0); (0, 0, 3, 0)] 

Обратите внимание, что вы можете также использовать List.filter:

let constrained_by (x,y,z,_) = List.filter (fun (x',y',z',_) -> x = x' or y=y' or z=z');;