Skip to content

Instantly share code, notes, and snippets.

@goose121
Created April 13, 2020 19:52
Show Gist options
  • Select an option

  • Save goose121/49504932fc3e156c76c64d2b47368b55 to your computer and use it in GitHub Desktop.

Select an option

Save goose121/49504932fc3e156c76c64d2b47368b55 to your computer and use it in GitHub Desktop.
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module EitherS
( EitherS(EitherS)
, runEitherS ) where
import Control.Applicative (Alternative, empty, (<|>))
import Data.Bifunctor (first)
newtype EitherS a b = EitherS { runEitherS :: Either a b }
deriving (Show, Eq, Ord, Functor, Foldable, Traversable)
instance Semigroup a => Applicative (EitherS a) where
pure = EitherS . pure
(EitherS (Right f)) <*> (EitherS (Right x)) = EitherS (Right (f x))
(EitherS (Left x)) <*> (EitherS (Right _)) = EitherS (Left x)
(EitherS (Right _)) <*> (EitherS (Left y)) = EitherS (Left y)
(EitherS (Left x)) <*> (EitherS (Left y)) = EitherS (Left (x <> y))
instance (Semigroup a, Semigroup b) => Semigroup (EitherS a b) where
x <> y = (<>) <$> x <*> y
instance (Semigroup a, Monoid b) => Monoid (EitherS a b) where
mempty = pure mempty
newtype FirstVal a = FirstVal { getFirstVal :: a }
instance Semigroup (FirstVal a) where
(<>) = const
instance (Monoid a) => Alternative (EitherS a) where
empty = EitherS (Left mempty)
x <|> y = getFirstVal <$> flipEitherS (flipEitherS (FirstVal <$> x) <> flipEitherS (FirstVal <$> y))
where
flipEitherS (EitherS (Left x)) = EitherS (Right x)
flipEitherS (EitherS (Right x)) = EitherS (Left x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment