Как сопоставить несколько условных шаблонов с одним результатом?

Попытка скомпилировать следующую функцию вызывает ошибку:

let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
  match left,ele,right with
  | N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
  | N (d',a,x,N (_,b,y,c)),z,d when d' - depth d > 1 && ele > x
  | a,x,N (d',N (_,b,y,c),z,d) when d' - depth a > 1 && ele < z
  | a,x,N (d',b,y,N (_,c,z,d)) when d' - depth a > 1 && ele > y
      -> new_node (new_node a x b) y (new_node c z d)
  | _ -> new_node left ele right

Однако обе следующие функции будут скомпилированы без проблем:

let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
  match left,ele,right with
  | N (d',N (_,a,x,b),y,c),z,d
  | N (d',a,x,N (_,b,y,c)),z,d
  | a,x,N (d',N (_,b,y,c),z,d)
  | a,x,N (d',b,y,N (_,c,z,d))
      -> new_node (new_node a x b) y (new_node c z d)
  | _ -> new_node left ele right
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
  match left,ele,right with
  | N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
      -> new_node (new_node a x b) y (new_node c z d)
  | _ -> new_node left ele right

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

Было бы очень хорошо, если бы вы могли включить ошибку, которую вы получаете. Когда я пробую первую функцию на try.ocamlpro.com, она дает мне Syntax Error, и эта синтаксическая ошибка возникает из-за неправильного использования when.

Nalin Ranjan 23.04.2022 06:12
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
1
34
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это правда, это ограничение паттернов OCaml.

Когда вы пишете это:

match x with
| 1
| 2 -> f x

На самом деле вы пишете только один шаблон, который выглядит так:

match x with
| (1 | 2) -> f x

Итак, это (если бы это было разрешено):

match x with
| 1 when a
| 2 when b -> f x

будет эквивалентно чему-то вроде этого:

match x with
| (1 when a | 2) when b -> f x

Другими словами, вы пытаетесь добавить предложения when в середину шаблона. Это не поддерживается. Это просто особенность match, а не паттернов в целом.

В дополнение к тому, что уже сказал Джеффри Скофилд, остерегайтесь следующей ловушки.

match 42 with 
| 1 
| n when n mod 2 = 0 -> "foo" 
| n -> "bar"

Или эквивалентно:

match 42 with 
| (1 | n) when n mod 2 = 0 -> "foo" 
| n -> "bar"

Оба получают эту ошибку:

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

Условная защита when должна работать для шаблона либо. Вот почему следующее будет работать.

match (3, 2) with 
| (1, n) 
| (3, n) when n mod 2 = 0 -> "foo" 
| n -> "bar"

Эквивалентно:

match (3, 2) with 
| ((1, n) | (3, n)) when n mod 2 = 0 -> "foo" 
| n -> "bar"

Будьте готовы к предупреждениям компилятора, если вы привязываете одно и то же имя к разным значениям, используя шаблоны, объединенные с помощью |.

Другие вопросы по теме