Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions Data/Primitive/SmallArray.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
, sizeofSmallArray
, getSizeofSmallMutableArray
, sizeofSmallMutableArray
, sameSmallArray
, sameSmallMutableArray
#if MIN_VERSION_base(4,14,0)
, shrinkSmallMutableArray
, resizeSmallMutableArray
Expand Down Expand Up @@ -93,7 +95,7 @@
import Language.Haskell.TH.Syntax (Lift(..))

data SmallArray a = SmallArray (SmallArray# a)
deriving Typeable

Check warning on line 98 in Data/Primitive/SmallArray.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.12)

• Deriving ‘Typeable’ has no effect: all types now auto-derive Typeable

#if MIN_VERSION_deepseq(1,4,3)
instance NFData1 SmallArray where
Expand All @@ -104,7 +106,7 @@
rnf = foldl' (\_ -> rnf) ()

data SmallMutableArray s a = SmallMutableArray (SmallMutableArray# s a)
deriving Typeable

Check warning on line 109 in Data/Primitive/SmallArray.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.12)

• Deriving ‘Typeable’ has no effect: all types now auto-derive Typeable

instance Lift a => Lift (SmallArray a) where
#if MIN_VERSION_template_haskell(2,16,0)
Expand Down Expand Up @@ -311,6 +313,28 @@
(# s', sma# #) -> (# s', SmallMutableArray sma# #)
{-# INLINE unsafeThawSmallArray #-}

-- | Check whether the two arrays refer to the same memory block.
sameSmallArray :: SmallArray a -> SmallArray a -> Bool
{-# INLINE sameSmallArray #-}
sameSmallArray (SmallArray sa1#) (SmallArray sa2#) =
#if MIN_VERSION_base(4,17,0)
isTrue# (sameSmallArray# sa1# sa2#)
#else
isTrue#
(reallyUnsafePtrEquality# (unsafeCoerce# sa1# :: ()) (unsafeCoerce# sa2# :: ()))
#endif

-- | Check whether the two arrays refer to the same memory block.
sameSmallMutableArray :: SmallMutableArray s a -> SmallMutableArray s a -> Bool
{-# INLINE sameSmallMutableArray #-}
sameSmallMutableArray (SmallMutableArray sma1#) (SmallMutableArray sma2#) =
#if MIN_VERSION_base(4,17,0)
isTrue# (sameSmallMutableArray# sma1# sma2#)
#else
isTrue#
(reallyUnsafePtrEquality# (unsafeCoerce# sma1# :: ()) (unsafeCoerce# sma2# :: ()))
#endif

-- | Copy a slice of an immutable array into a mutable array.
--
-- /Note:/ this function does not do bounds or overlap checking.
Expand Down Expand Up @@ -396,7 +420,7 @@
-- 'getSizeofSmallMutableArray' instead.
sizeofSmallMutableArray :: SmallMutableArray s a -> Int
sizeofSmallMutableArray (SmallMutableArray sa#) =
I# (sizeofSmallMutableArray# sa#)

Check warning on line 423 in Data/Primitive/SmallArray.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.12)

In the use of ‘sizeofSmallMutableArray#’

Check warning on line 423 in Data/Primitive/SmallArray.hs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 9.12)

In the use of ‘sizeofSmallMutableArray#’
{-# DEPRECATED sizeofSmallMutableArray "use getSizeofSmallMutableArray instead" #-}
{-# INLINE sizeofSmallMutableArray #-}

Expand Down Expand Up @@ -521,11 +545,11 @@
liftEq = smallArrayLiftEq

instance Eq a => Eq (SmallArray a) where
sa1 == sa2 = smallArrayLiftEq (==) sa1 sa2
sa1 == sa2 = sameSmallArray sa1 sa2 || smallArrayLiftEq (==) sa1 sa2

instance Eq (SmallMutableArray s a) where
SmallMutableArray sma1# == SmallMutableArray sma2# =
Copy link
Member

Choose a reason for hiding this comment

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

Can the Eq instance for SmallArray not be similarly cleaned up?

Copy link
Member Author

Choose a reason for hiding this comment

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

As opposed to the instance for SmallMutableArray, the instance for SmallArray can return True, when the arrays are not in the same memory location, but have same the elements. We can use sameSmallArray to enable short-circuiting though! :)

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, short-circuiting was the desired cleanup. Thank you!

Copy link

Choose a reason for hiding this comment

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

There's problem with floating point and lawless Eq instances. With sameSmallArray shortcut
let x=[nan] in x==x returns True but let x=[nan]; y=[nan] in x==y returns False.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's problem with floating point and lawless Eq instances. With sameSmallArray shortcut let x=[nan] in x==x returns True but let x=[nan]; y=[nan] in x==y returns False.

Floating point is indeed a problem... Did @sjakobi do some recent pointer equality stuff in unordered-containers, or did @meooow25 do it in containers?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm. This is unfortunate, but I think it's acceptable that broken Eq instances don't interact well with the Eq instances of container types. Users can still resort to liftEq (==) if necessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

Did @sjakobi do some recent pointer equality stuff in unordered-containers,

I did some, but I don't think it affects the Eq instances for HashMap or HashSet.

Copy link
Contributor

Choose a reason for hiding this comment

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

Did @sjakobi do some recent pointer equality stuff in unordered-containers,

I did some, but I don't think it affects the Eq instances for HashMap or HashSet.

Oh right, some bulk operation stuff. Regardless, we might want to document that floating point NaNs are not suitable for use as keys, If we haven't already.

isTrue# (sameSmallMutableArray# sma1# sma2#)
sameSmallMutableArray (SmallMutableArray sma1#) (SmallMutableArray sma2#)

smallArrayLiftCompare :: (a -> b -> Ordering) -> SmallArray a -> SmallArray b -> Ordering
smallArrayLiftCompare elemCompare a1 a2 = loop 0
Expand Down
Loading