ekmett / lens

Lenses, Folds, and Traversals - Join us on web.libera.chat #haskell-lens
http://lens.github.io/
Other
2.03k stars 272 forks source link

Add ‘allEqualOf’ #685

Open Icelandjack opened 7 years ago

Icelandjack commented 7 years ago

Even though it's not in Data.List it would be cool to have a Fold for testing if all elements are the same. Sketch of an implementation, comment if you have a nicer way of constructing this Monoid, maybe with First and All

import Control.Lens
import Data.Semigroup
import Data.Monoid hiding ((<>))

data Same a = SeenNone | SeenSame a | Nope

instance Eq a => Semigroup (Same a) where
  SeenNone   <> a        = a
  a          <> SeenNone = a
  SeenSame a <> SeenSame b
    | a == b = SeenSame a
  _          <> _        = Nope

instance Eq a => Monoid (Same a) where
  mempty  = SeenNone
  mappend = (<>)

theSame :: Same a -> Bool
theSame = \case
  SeenNone   -> True
  SeenSame{} -> True
  Nope       -> False

-- allEqualOf :: Eq a => Fold s a -> s -> Bool
allEqualOf :: Getting (Same a) s a -> s -> Bool
allEqualOf ℓ = theSame . foldMapOf ℓ SeenSame

Other names allSameOf, allEqualOf, equalOf, allTheSameOf.

>>> __ = error "..."
>>> allEqualOf both (Left __)
True
>>> allEqualOf traverse (__, __)
True
>>> allEqualOf both ('a', 'a')
True
>>> allEqualOf both ('a', 'b')
False
>>> allEqualOf (folded.folded.both.folded) [Just ("aaaa", "aa"), Nothing, Just ("a", "")]
True
Icelandjack commented 7 years ago

Giving

allEqual :: (Foldable f, Eq a) => f a -> Bool
allEqual = allEqualOf folded
Zemyla commented 7 years ago

You'll want to put the Nope matches at the top, so Nopes propagate quicker. Nope <> _ = Nope means that it can completely ignore searching on the right if the left returns a negative result.

ekmett commented 7 years ago

On the plus side its fairly easy to implement. On the downside, we tend to avoid fooBar style names in lens, with the exception of 'Of' so the name seems a bit off for us.

AnthonySuper commented 5 years ago

The naming omniequalOf would avoid the fooBar problem at the probable cost of clarity.