Как стать автором
Обновить
4
0
Maverik @Maverik

Пользователь

Отправить сообщение

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

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

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

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

Время на прочтение4 мин
Количество просмотров7.7K
Наверное, все знают, что при вычислениях с ограниченной точностью два математически эквивалентных выражения могут оказаться не равны друг другу. Например, следующее очевидное математическое равенство при вычислении в 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.

Читать дальше →
Всего голосов 20: ↑15 и ↓5+10
Комментарии15

Информация

В рейтинге
Не участвует
Откуда
Макеевка, Донецкая обл., Украина
Дата рождения
Зарегистрирован
Активность