2012-04-18 2 views
1

Почему я получаю ошибки, когда я пишу этот вид поиска по шаблону:соответствия шаблона и конструкторы

type t = A of int | B of float 

let f = function 
     | (A i | B f) -> true 
     | _ -> false 

или

let f = function 
     | A i | B f -> true 
     | _ -> false 

Error: Variable f must occur on both sides of this | pattern

let f = function 
     | (A i | B i) -> true 
     | _ -> false 

или

let f = function 
     | A i | B i -> true 
     | _ -> false 

Error: This pattern matches values of type ints of type float but a pattern was expected which matches value

ответ

8

Если обеспечить единую правую для нескольких моделей (как вы делаете), OCaml требует, чтобы шаблоны последовательно связывались с переменными шаблона.

В первой ситуации,

match ... with 
    | A i | B f -> ... 
    ... 

узоры не согласны на переменные, которые они связывают с: первый шаблон связывается с i, в то время как второй привязок к f.

Во второй ситуации,

match ... with 
    | A i | B i -> ... 
    ... 

узоры не договариваются о типе значений для связывания с их переменными: первый шаблон связывает значение типа int к i, в то время как второй, связывается значение типа float - i.

Единственный способ, в котором эти две картины могут последовательно связываются с переменными не связываться с любыми переменными вообще:

match ... with 
    | A _ | B _ -> ... 
    ... 

Полный пример становится

type t = A of int | B of float 

let f = function 
    | A _ | B _ -> true 
    | _ -> false 

(Но обратите внимание, что последний рычаг совпадения рисунка лишний, поскольку первые два образца уже исчерпывающе соответствуют всем значениям вашего типа t. Следовательно, мы получаем:

let f = function 
    | A _ | B _ -> true 

Это, конечно, эквивалентно написанию let f _ = true.)

3

В Or шаблоне (| шаблона), вы теряете след которых конструктор вы находитесь. Таким образом, вы должны связать один и тот же набор переменных, чтобы работать, не обращаясь к конструкторам.

И OCaml строго типизирован; значение i не может иметь тип int и тип float.

Если тип t имеет более чем два случая, вы должны написать:

let f = function 
     | A _ | B _ -> true 
     | _ -> false 

иначе:

let f = function 
     | A _ | B _ -> true 

достаточно, так как соответствующий шаблон уже исчерпывающими.

Я согласен, что Or картина весьма ограничительный характер, но иногда это полезно, когда у вас есть симметричные случаи в вашей функции:

type num = 
    | Int of int 
    | Float of float 

let add s1 s2 = 
    match s1, s2 with 
    | Int i1, Int i2 -> Int (i1 + i2) 
    | Int i, Float f | Float f, Int i -> Float (float i +. f) 
    | Float f1, Float f2 -> Float (f1 +. f2) 
Смежные вопросы