В F#, оператор равенства (=) обычно пространственно, а не интенсионален.Здорово! К сожалению, кажется мне, что F# не использует равенство указателя ярлыку эти пространственные сравнения.
Например, этот код:
type Z = MT | NMT of Z ref // create a Z: let a = ref MT // make it point to itself: a := NMT a // check to see whether it's equal to itself: printf "a = a: %A\n" (a = a)
... дает мне большой отказ сегментации [*], несмотря на то, что и оба оценивают к той же ссылке. Это не является настолько большим. Другие функциональные языки (например, Схема PLT) разбираются в этом, с помощью сравнений указателя консервативно, для возвращения 'true', когда это может быть определено с помощью сравнения указателя.
Так: я приму то, что оператор равенства F# не использует сокращенный; там некоторый путь состоит в том, чтобы выполнить интенсиональную (основанную на указателе) проверку равенства? (==) оператор не определяется на моих типах, и я любил бы его, если кто-то мог бы сказать мне, что это доступно так или иначе.
Или скажите мне, что я неправ в своем анализе ситуации: я любил бы это, также...
[*], Который, вероятно, был бы переполнением стека в Windows; существуют вещи о Моно, который я настолько не люблю...
Мне известны два варианта. Стандартный подход .NET заключается в использовании System.Object.ReferenceEquals
. Немного лучшим подходом в F # может быть использование LanguagePrimitives.PhysicalEquality
, который в основном идентичен, но работает только со ссылочными типами (что, вероятно, правильно для ваших целей) и требует, чтобы оба аргумента имели один и тот же статический тип. Вы также можете определить пользовательский оператор по вашему выбору в терминах любой из этих функций, если вам нужен более удобный синтаксис.
Кстати, в .NET я получаю бесконечный цикл, но не переполнение стека, когда я запускаю ваш код, предположительно из-за оптимизации хвостового вызова.