Ответ 1
Может быть, вам нужен тип Maybe?
data Infinite a = Infinite | Only a
тогда напишите экземпляр Num для Num a = > Infinite a, с требуемыми числовыми правилами.
Я пытаюсь реализовать структуру данных, где, если бы я использовал бесконечность для целей численного сравнения, это было бы очень просто. Обратите внимание, что это не maxBound/minBound, поскольку значение может быть <= maxbound, но все значения будут равны < бесконечность.
Нет надежды?
Может быть, вам нужен тип Maybe?
data Infinite a = Infinite | Only a
тогда напишите экземпляр Num для Num a = > Infinite a, с требуемыми числовыми правилами.
Ну как насчет этого! Оказывается, если вы просто наберете 1/0
, он вернет Infinity
! На ghci:
Prelude> 1/0
Infinity
Prelude> :t 1/0
1/0 :: (Fractional t) => t
Prelude> let inf=1/0
Prelude> filter (>=inf) [1..]
а затем, конечно, он работает вечно, никогда не найдя число больше бесконечности. (Но см. Подробные комментарии ниже о фактическом поведении [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, которая делает это очень просто. Я определил тип "Граница", так что значение типа "Граница а" всегда либо выше, либо ниже любого "а". Границы могут быть "AboveAll", "BelowAll", "Above 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
, с другими желаниями, которые вы, возможно, захотите, включая +/- бесконечность, +/- бесконечно малые, бесконечно малые числа второго порядка и т.д. Но обратите внимание, что это не архимедиан и индукция больше не будут работать, что является своего рода арифметикой второго порядка. Для реализации взгляните на этот пример. Как и в комментарии в коде, эта конструкция должна работать для других алгебр, таких как монада списка. Вы можете думать о списках, где два элемента "бесконечно близки" "бесконечно далеко" и т.д. (Что приводит к обобщению розовых деревьев.)