Search
Write a publication
Pull to refresh
4
0.1
Maverik @Maverik

User

Send message

Проблемы, вызванные определением кортежей как функторов

Reading time8 min
Views5.6K
Очень удивительно (я бы даже сказал — внезапно!), но кортеж-пара в GHC является функтором. Это сложно понять, ведь функтор должен иметь только один параметр, а у пары их два. Можно восхищаться тем, как разработчики стандартной библиотеки GHC умудрились предоставить такую абстракцию, но мне кажется, полученное решение все же следует признать неудачным.

Начнем с того, что оно интуитивно непонятно. Скажем, попробуйте вычислить вручную, не используя инструментов GHC, выражение (1+) `fmap` (2, 3). А после этого проверьте полученный результат, например, в ghci. У многих ли результат ручного вычисления совпал с тем, который выдала система? И если у вас результаты все же совпали, мне очень хотелось бы услышать хорошее объяснение того, как именно вам это удалось.
Читать дальше →

Приближенное сравнение чисел в Haskell

Reading time4 min
Views7.8K
Наверное, все знают, что при вычислениях с ограниченной точностью два математически эквивалентных выражения могут оказаться не равны друг другу. Например, следующее очевидное математическое равенство при вычислении в Haskell неожиданно оказывается ложным:

ghci> 3 * sqrt(24 ^ 2 + 16 ^ 2) == sqrt(72 ^ 2 + 48 ^ 2)
False


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

ghci> 3 * sqrt(24 ^ 2 + 16 ^ 2)
86.53323061113574
ghci> sqrt(72 ^ 2 + 48 ^ 2)
86.53323061113575
ghci> sqrt(72 ^ 2 + 48 ^ 2) - 3 * sqrt(24 ^ 2 + 16 ^ 2)
1.4210854715202004e-14


Различие здесь только в последнем (четырнадцатом!) знаке после запятой, но этого уже достаточно, чтобы сравнение оказалось ложным.

Несмотря на то, что эта проблема хорошо известна, программисты уделяют ей мало внимания. Во-первых, считается, что сравнения такого рода возникают только в узкой области численных методов, а во-вторых, что нарушение равенства происходит крайне редко. Как оказалось, и то и другое не совсем верно. Приведенный случай возник, когда мне понадобилось реализовать функцию вычисления длины вектора с целочисленными координатами. При этом для модульного тестирования используются средства пакета QuickCheck, который довольно быстро нашел случай нарушения инварианта масштабирования для длины вектора. Замечу, что это далеко не единственный инвариант, нарушение которого было обнаружено при тестировании.

Возникает вопрос: как проще всего описать проверку приблизительного равенства двух чисел, полученных в результате вычислений с ограниченной точностью? Для решения этой задачи в Haskell достаточно определить еще один оператор сравнения (скажем, ~=), который используется так же, как и обычный оператор равенства. Предлагаю рассмотреть реализацию такого оператора, которую можно оформить в виде достаточно простого модуля Circa.

Читать дальше →

Information

Rating
7,536-th
Location
Макеевка, Донецкая обл., Украина
Date of birth
Registered
Activity