haskellari / these

An either-or-both data type, with corresponding hybrid error/writer monad transformer.
117 stars 49 forks source link

Equivalence for These #157

Open subttle opened 3 years ago

subttle commented 3 years ago

Hi, thank you for your very useful package and all the hard work you put into it. I have minor suggestion to add an equivalence relation (Equivalence from Data.Functor.Contravariant)

import Data.Functor.Contravariant (Equivalence (..))

eqThese :: Equivalence (These a b)
eqThese = Equivalence equivalence
  where
    equivalence :: These a b -> These a b -> Bool
    equivalence (This  _  ) (This  _  ) = True
    equivalence (That    _) (That    _) = True
    equivalence (These _ _) (These _ _) = True
    equivalence _           _           = False

I've made similar equivalence relations for other types (e.g. such as Smash, Can, Wedge, and have found them quite useful [1]). If you are interested I can make a pull request. If you don't see the need to add this for what ever reason I won't take offense.

Please let me know what you think. I hope you have a great day!

[1] https://github.com/emilypi/smash/issues/23

Edit removed UnicodeSyntax and updated naming convention to match the one now used by smash.

phadej commented 3 years ago

I'm missing something. In your example in smash

graphComponents ∷ ∀ a . (Num a, Eq a) ⇒ Equivalence (a, a)
graphComponents = contramap getComponents byCan
  where
    getComponents ∷ (a, a) → Can a a
    getComponents (0, 0) = Non     -- origin
    getComponents (x, 0) = One x   -- x-axis
    getComponents (0, y) = Eno   y -- y-axis
    getComponents (x, y) = Two x y -- quadrant

which doesn't use Eq a. What am I missing?

subttle commented 3 years ago

The Eq a constraint in this case is required to check if an a is equal to 0. If you're asking to see it demonstrated I can give you an example:

λ> graphComponents @ Fin₃
[[(0,0)],[(0,1),(0,2)],[(1,0),(2,0)],[(1,1),(1,2),(2,1),(2,2)]]