Max и min с NaN в Haskell
Почему макс NaN и число NaN, но min NaN и число - это число? Это, похоже, противоречит нескольким другим языкам, которые я пробовал:
В Haskell:
max (0/0) 1 -- NaN
min (0/0) 1 -- 1.0
В Python
>>> max(float("nan"),1) #nan
>>> min(float("nan"),1) #nan
В JavaScript
> Math.max(0/0,1) //NaN
> Math.min(0/0,1) //NaN
Ответы
Ответ 1
В отчете Haskell указано, что (min x y, max x y)
вернет либо (x, y)
, либо (y, x)
. Это приятное свойство, но трудно примириться с симметричной обработкой NaN.
Также стоит упомянуть, что это точно та же асимметрия, что и команды SSE2 MINSD
и MAXSD
, т.е. Haskell min
(для Double
) может быть реализована с помощью MINSD
и max
на MAXSD
.
Ответ 2
Не совсем, min 1.0 (0/0)
вернет NaN, например.
Это связано с тем, что любое сравнение с NaN определяется как возвращаемое значение false, а по определению min и max ниже:
max x y
| x <= y = y
| otherwise = x
min x y
| x <= y = x
| otherwise = y
min и max с NaN вернут второй и первый аргументы соответственно.
Ответ 3
Я не программист Haskell, но кажется, что функции с плавающей запятой называются fmin
и fmax
. По какой-то причине общие функции, применяемые к типам с плавающей запятой, не соответствуют стандартным числовым поведением.
fmin
и fmax
соответствуют требованиям IEEE 754: 2008 §5.3.1:
minNum (x, y) является каноническим числом x, если x < y, y, если y < x, каноническое число, если один операнд является числом, а другой - тихим NaN.
Обратите внимание, что это поведение противоположно JavaScript. Не делайте так, как это делает JavaScript: v).