Сопоставление с образцом и конструкторы
Почему я получаю ошибки, когда пишу такой тип сопоставления:
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
Ошибка: переменная f должна встречаться по обе стороны от этого | шаблон
let f = function
| (A i | B i) -> true
| _ -> false
или же
let f = function
| A i | B i -> true
| _ -> false
Ошибка: этот шаблон соответствует значениям типа int типа float, но ожидался шаблон, соответствующий значению
2 ответа
Если вы предоставляете одну правую часть для нескольких шаблонов (как вы делаете), 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
.)
В 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)