bifunctors icon indicating copy to clipboard operation
bifunctors copied to clipboard

Added instances of Semigroup, Monoid; Bounded, Enum, Ix; and Storable where appropriate

Open duairc opened this issue 9 years ago • 4 comments

duairc avatar Dec 23 '15 13:12 duairc

@ekmett, I'd like to get your opinion on the Semigroup instances for Biff and Tannen since they are bifunctors' variants of Compose from Data.Functor.Compose, and that you had expressed reservations about a Semigroup (f (g a)) => Semigroup (Compose f g a) instance here.

RyanGlScott avatar Dec 23 '15 16:12 RyanGlScott

I think in light of the objections raised in base, the same objections hold here. If we supply instances for Eq, Show, Read, Ord that they should use Data.Functor.Classes via transformers-compat / transformers on older GHCs and base on GHC 8+ and leave off things like Semigroup for the same reasons given there.

ekmett avatar Dec 23 '15 20:12 ekmett

@duairc As far as Monoid goes... perhaps you'd find a typeclass like Bialternative useful?

module Data.Bialternative where

import Control.Applicative

import Data.Biapplicative
import Data.Bifunctor.Biff
import Data.Bifunctor.Clown
import Data.Bifunctor.Flip
import Data.Bifunctor.Joker
import Data.Bifunctor.Product
import Data.Bifunctor.Tannen
import Data.Bifunctor.Wrapped

-- | A monoid on applicative 'Bifunctor's.
--
-- If defined, 'bisome' and 'bimany' should be the least solutions
-- of the equations:
--
-- * @'bisome' v = 'bimap' (:) (:) v '<<*>>' 'bimany' v@
--
-- * @'bimany' v = 'bisome' v '<<|>>' 'bipure' [] []@
class Biapplicative f => Bialternative f where
  -- | The identity of '<<|>>'
  biempty :: f a b
  -- | An associative binary operation
  (<<|>>) :: f a b -> f a b -> f a b

  -- | One or more.
  bisome :: f a b -> f [a] [b]
  bisome v = bisome_v
    where
      bimany_v = bisome_v <<|>> bipure [] []
      bisome_v = (bimap (:) (:) v) <<*>> bimany_v

  -- | Zero or more.
  bimany :: f a b -> f [a] [b]
  bimany v = bimany_v
    where
      bimany_v = bisome_v <<|>> bipure [] []
      bisome_v = (bimap (:) (:) v) <<*>> bimany_v

instance (Biapplicative p, Alternative f, Alternative g) => Bialternative (Biff p f g) whe
re
  biempty = Biff (bipure empty empty)
  Biff x <<|>> Biff y = Biff (biliftA2 (<|>) (<|>) x y)

instance Alternative f => Bialternative (Clown f) where
  biempty = Clown empty
  Clown x <<|>> Clown y = Clown (x <|> y)

instance Bialternative p => Bialternative (Flip p) where
  biempty = Flip biempty
  Flip x <<|>> Flip y = Flip (x <<|>> y)

instance Alternative f => Bialternative (Joker f) where
  biempty = Joker empty
  Joker x <<|>> Joker y = Joker (x <|> y)

instance (Bialternative f, Bialternative g) => Bialternative (Product f g) where
  biempty = Pair biempty biempty
  Pair w x <<|>> Pair y z = Pair (w <<|>> y) (x <<|>> z)

instance (Applicative f, Bialternative p) => Bialternative (Tannen f p) where
  biempty = Tannen (pure biempty)
  Tannen x <<|>> Tannen y = Tannen (liftA2 (<<|>>) x y)

instance Bialternative f => Bialternative (WrappedBifunctor f) where
  biempty = WrapBifunctor biempty
  WrapBifunctor x <<|>> WrapBifunctor y = WrapBifunctor (x <<|>> y)

This would give a Haskell98 way to combine values of * -> * -> *-kinded types. If you wanted an analog for Semigroup, we could also consider adding classes like Bialt to semigroupoids.

RyanGlScott avatar Aug 14 '16 17:08 RyanGlScott

Nobody has shown me any good usecases for Biapplicatives, let alone Bialternatives. =(

ekmett avatar Aug 14 '16 20:08 ekmett