Skip to content
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
"devDependencies": {
"purescript-console": "^4.0.0",
"purescript-exceptions": "^4.0.0"
},
"dependencies": {
"purescript-prelude": "^4.1.0"
}
}
21 changes: 21 additions & 0 deletions src/Unsafe/Reference.purs
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
module Unsafe.Reference
( unsafeRefEq
, reallyUnsafeRefEq
, UnsafeRefEq (..)
, UnsafeRefEqFallback (..)
) where

import Prelude

-- | Compares two values of the same type using strict (`===`) equality.
unsafeRefEq :: forall a. a -> a -> Boolean
unsafeRefEq = reallyUnsafeRefEq

-- | Compares two values of different types using strict (`===`) equality.
foreign import reallyUnsafeRefEq :: forall a b. a -> b -> Boolean

-- | The `Eq` instance is defined by `unsafeRefEq`.
newtype UnsafeRefEq a = UnsafeRefEq a

instance eqUnsafeRefEq :: Eq (UnsafeRefEq a) where
eq (UnsafeRefEq l) (UnsafeRefEq r) = unsafeRefEq l r

-- | The `Eq` instance first checks `unsafeRefEq`, if `false` falls back to
-- | the underlying `Eq` instance.
newtype UnsafeRefEqFallback a = UnsafeRefEqFallback a

instance eqUnsafeRefEqFallback ::
Eq a =>
Eq (UnsafeRefEqFallback a) where
eq (UnsafeRefEqFallback l) (UnsafeRefEqFallback r) =
unsafeRefEq l r || l == r

10 changes: 9 additions & 1 deletion test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Prelude
import Effect (Effect)
import Effect.Exception (throwException, error)

import Unsafe.Reference (unsafeRefEq, reallyUnsafeRefEq)
import Unsafe.Reference (unsafeRefEq, reallyUnsafeRefEq, UnsafeRefEq(..), UnsafeRefEqFallback(..))

data Foo = Foo String
data Bar = Bar String
Expand All @@ -17,6 +17,10 @@ assert :: Boolean -> String -> Effect Unit
assert true _ = pure unit
assert _ desc = throwException (error desc)

data X = Y Unit | Z

derive instance eqX :: Eq X

main :: Effect Unit
main = do
let
Expand All @@ -32,3 +36,7 @@ main = do
assert (unsafeRefEq foo3 foo4) "unsafeRefEq newtype"
assert (reallyUnsafeRefEq foo3 bar2) "reallyUnsafeRefEq newtype"
assert (not reallyUnsafeRefEq foo1 bar1) "not reqallyUnsafeRefEq data"
assert (UnsafeRefEq 0 == UnsafeRefEq 0) "UnsafeRefEq eq with identical values"
assert (UnsafeRefEq (Y unit) /= UnsafeRefEq (Y unit)) "UnsafeRefEq not eq with non-identical values"
assert (UnsafeRefEqFallback (Y unit) == UnsafeRefEqFallback (Y unit)) "UnsafeRefEqFallback eq with non-identical but equal values"
assert (UnsafeRefEqFallback (Y unit) /= UnsafeRefEqFallback Z) "UnsafeRefEqFallback not eq with non equal values"