Есть ли лучший способ написать коммутативную функцию на F#/OCaml?

Есть ли более элегантный или лучший способ написать коммутативную функцию на F#/OCaml вместо перечисления всех возможных случаев?

let commutative x y = 
    match x,y with
        a, _ -> val1
       |_, a -> val1
       |b, _ -> val2
       |_, b -> val2
       ...
       |_,z -> |valN

Пока я писал вопрос, я подумал, что можно сделать функцию рекурсивной и поменять местами аргументы, если совпадение не найдено.

let rec commutative x y = 
    match x,y with
     a,_ -> val1
    |b,_ -> val2
     ...
    |nox,noy -> commutative noy nox

Но если я приму этот подход, я не смогу иметь в функции случай по умолчанию, который соответствует всем, если я не добавлю еще один аргумент, значение которого указывает, вызывается ли функция во второй раз, и возвращаю значение по умолчанию вместо вызова функции с замененным аргументы, если это так.

Любые другие идеи? Предлагает ли язык конструкцию для выражения того факта, что функция, которую я определяю, является коммутативной?


person Gerardo Zinno    schedule 24.12.2019    source источник
comment
В ocaml у вас может быть несколько совпадений, если они охватывают одни и те же переменные с одинаковыми типами. Например, вы можете написать | a, _ | _, a -> val1.   -  person Dan Robertson    schedule 25.12.2019


Ответы (1)


(Я отвечаю только за OCaml, так как мой F# очень ржавый.)

В OCaml нет специальной помощи для определения коммутативных функций.

Если ваш тип параметра имеет разумное отношение порядка, вы можете при необходимости поменять их местами, чтобы сделать x больше (скажем). В OCaml можно сравнивать почти все типы, так что это должно работать очень часто. (Вещи, которые нельзя сравнивать: типы функций, циклические значения.)

Я не уверен, что это поможет, но может уменьшить количество случаев, которые вам нужно записать:

let commutative x y =
    match (max x y, min x y) with
    | A, _ -> value
    . . .
person Jeffrey Scofield    schedule 24.12.2019
comment
В F# вы можете написать это, но проверка полноты в матче не будет учитывать функции max и min, поэтому таким образом вы потеряете безопасность. - person Charles Roddie; 28.12.2019
comment
По вашему опыту, это что-то делается на практике? Или люди просто пишут все дела? - person Gerardo Zinno; 21.06.2020
comment
Я не так часто вижу такой код, поэтому могу только высказать свое мнение. Это стоит некоторых дополнительных вычислений, чтобы сделать код более понятным. Но при написании библиотеки вы часто пишете более эффективный код, который немного менее понятен, потому что это может иметь большое значение, когда вызов заканчивается во внутреннем цикле. Если я пишу свой собственный код, я мог бы использовать метод упорядочения; при написании библиотеки я бы подумал о том, чтобы просто написать все случаи. OCaml превосходно следит за тем, чтобы вы не забыли дело. - person Jeffrey Scofield; 22.06.2020