В Haskell есть бесконечность: Num a => a?

Я пытаюсь реализовать структуру данных, где, если бы я использовал бесконечность для численных целей сравнения, это было бы просто очень. Обратите внимание, что это не maxBound/minBound, потому что значение может быть

никакой надежды?

8 ответов


может быть, вы хотите тип может быть?

data Infinite a = Infinite | Only a

затем напишите экземпляр Num для Num a = > Infinite a, с числовыми правилами, которые вам нужны.


Ну как про что! Оказывается, если вы просто наберете 1/0 возвращает Infinity! На ГГц:

Prelude> 1/0
Infinity
Prelude> :t 1/0
1/0 :: (Fractional t) => t
Prelude> let inf=1/0
Prelude> filter (>=inf) [1..]

и тогда, конечно, он работает вечно, никогда не находя числа больше бесконечности. (Но СМ. комментарии ephemient ниже о фактическом поведении [1..])


infinity = read "Infinity"

попробуйте что-то вроде этого. Однако, чтобы получить Num операции (например,+ или -) вам нужно будет определить Num экземпляр Infinitable a тип. Так же, как я сделал это для Ord класса.

data Infinitable a = Regular a | NegativeInfinity | PositiveInfinity deriving (Eq, Show)

instance Ord a => Ord (Infinitable a) where
    compare NegativeInfinity NegativeInfinity = EQ
    compare PositiveInfinity PositiveInfinity = EQ
    compare NegativeInfinity _ = LT
    compare PositiveInfinity _ = GT
    compare _ PositiveInfinity = LT
    compare _ NegativeInfinity = GT
    compare (Regular x) (Regular y) = compare x y    

main =
    let five = Regular 5
        pinf = PositiveInfinity::Infinitable Integer
        ninf = NegativeInfinity::Infinitable Integer
        results = [(pinf > five), (ninf < pinf), (five > ninf)]
    in
        do putStrLn (show results)

λ: let infinity = (read "Infinity")::Double
λ: infinity > 1e100
True
λ: -infinity < -1e100
True

взгляните на мой библиотека RangedSets, который делает именно это в очень общем виде. Я определил тип " границы "так, чтобы значение типа" граница a "всегда было выше или ниже любого заданного"a". Границы могут быть "AboveAll", "BelowAll", "выше x"и" ниже x".


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

type Bound a = Maybe a

withinBounds :: (Num a, Ord a) => Bound a -> Bound a -> a -> Bool
withinBounds lo hi v = maybe True (<=v) lo && maybe True (v<=) hi

существует более принципиальный подход, основанный на идее нестандартного анализа. Учитывая полностью упорядоченное кольцо R нулевой характеристики, можно рассматривать кольцо Лорана R[inf, 1 / inf] с естественным лексикографическим полным упорядочением. Например, у вас есть:

for all x>0 in R,
.. -inf < -x < -d < -d^2 < .. < 0 < .. < d^2 < d < x < inf < inf^2 < .. 
where d = 1/inf.

таким образом,кольцо Лорана R[inf, 1/inf] снова является полностью упорядоченной Z-алгеброй, то есть экземпляром Num, с другими тонкостями, которые вы, возможно, хотите, включая + / - бесконечность, + / - бесконечно малый, второго порядка бесконечно малые и т. д.. Но обратите внимание, что это не Архимед, и индукция больше не будет работать, что является своего рода арифметикой второго порядка. Для реализации взгляните на . Как и в комментарии в коде, эта конструкция должна работать для других алгебр, таких как монада списка. Вы можете думать о списках, где два элемента "бесконечно близки", "бесконечно далеки" второго порядка и т. д. (что приводит к обобщению розовых деревьев.)