Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Notable changes to this project are documented in this file. The format is based
## [Unreleased]

Breaking changes:
- Fix `signum zero` to return `zero` (#280 by @JordanMartinez)

New features:

Expand Down
12 changes: 9 additions & 3 deletions src/Data/Ord.purs
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,16 @@ between low hi x
abs :: forall a. Ord a => Ring a => a -> a
abs x = if x >= zero then x else negate x

-- | The sign function; always evaluates to either `one` or `negate one`. For
-- | any `x`, we should have `signum x * abs x == x`.
-- | The sign function; returns `one` if the argument is positive,
-- | `negate one` if the argument is negative, or `zero` if the argument is `zero`.
-- | For floating point numbers with signed zeroes, when called with a zero,
-- | this function returns the argument in order to preserve the sign
-- | For any `x`, we should have `signum x * abs x == x`.
signum :: forall a. Ord a => Ring a => a -> a
signum x = if x >= zero then one else negate one
signum x =
if x < zero then negate one
else if x > zero then one
else x

-- | The `Ord1` type class represents totally ordered type constructors.
class Eq1 f <= Ord1 f where
Expand Down
8 changes: 7 additions & 1 deletion test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Test.Main where

import Prelude
import Data.HeytingAlgebra (ff, tt, implies)
import Data.Ord (abs)
import Data.Ord (abs, signum)
import Test.Data.Generic.Rep (testGenericRep)
import Test.Utils (AlmostEff, assert)

Expand All @@ -15,6 +15,7 @@ main = do
testIntDegree
testRecordInstances
testGenericRep
testSignum

foreign import testNumberShow :: (Number -> String) -> AlmostEff

Expand Down Expand Up @@ -151,3 +152,8 @@ testRecordInstances = do
assert "Record top" $
(top :: { a :: Boolean }).a
== top

testSignum :: AlmostEff
testSignum = do
assert "signum positive zero" $ signum 0.0 == 0.0
assert "signum negative zero" $ signum (-0.0) == (-0.0)
Copy link
Contributor

@hdgarrood hdgarrood Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work unfortunately - positive zero compares equal to negative zero. Maybe try show-ing the result?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the test to

assert ("signum negative zero: " <> show (signum (-0.0))) $ show (signum (-0.0)) == "-0.0"

produces this error:

Error: signum negative zero: 0.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And assert (show (-0.0)) $ false produces Error: 0.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like Object.is is a way to verify this.