{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE LambdaCase #-}
module Haskus.Utils.Variant.VEither
( VEither
, pattern VLeft
, pattern VRight
, veitherFromVariant
, veitherToVariant
, veitherToValue
, veitherBimap
, VEitherLift
, veitherLift
, veitherAppend
, veitherPrepend
, veitherCont
, veitherToEither
, veitherProduct
, module Haskus.Utils.Variant
)
where
import Haskus.Utils.Variant
import Haskus.Utils.Types
import Data.Coerce
newtype VEither es a
= VEither (V (a ': es))
pattern VLeft :: forall x xs. V xs -> VEither xs x
pattern VLeft xs <- ((popVariantHead . veitherToVariant) -> Left xs)
where
VLeft xs = VEither (toVariantTail xs)
pattern VRight :: forall x xs. x -> VEither xs x
pattern VRight x <- ((popVariantHead . veitherToVariant) -> Right x)
where
VRight x = VEither (toVariantHead x)
{-# COMPLETE VLeft,VRight #-}
instance
( Show a
, Show (V es)
) => Show (VEither es a) where
showsPrec d v = showParen (d /= 0) $ case v of
VLeft xs -> showString "VLeft "
. showsPrec 10 xs
VRight x -> showString "VRight "
. showsPrec 10 x
veitherFromVariant :: V (a ': es) -> VEither es a
{-# INLINABLE veitherFromVariant #-}
veitherFromVariant = VEither
veitherToVariant :: VEither es a -> V (a ': es)
{-# INLINABLE veitherToVariant #-}
veitherToVariant (VEither x) = x
veitherToEither :: VEither es a -> Either (V es) a
{-# INLINABLE veitherToEither #-}
veitherToEither = \case
VLeft xs -> Left xs
VRight x -> Right x
veitherToValue :: forall a. VEither '[] a -> a
{-# INLINABLE veitherToValue #-}
veitherToValue = coerce (variantToValue @a)
veitherBimap :: (V es -> V fs) -> (a -> b) -> VEither es a -> VEither fs b
{-# INLINABLE veitherBimap #-}
veitherBimap f g v = case v of
VLeft xs -> VLeft (f xs)
VRight x -> VRight (g x)
type VEitherLift es es' =
( LiftVariant es es'
)
veitherLift :: forall es' es a.
( VEitherLift es es'
) => VEither es a -> VEither es' a
{-# INLINABLE veitherLift #-}
veitherLift = veitherBimap liftVariant id
veitherPrepend :: forall ns es a.
( KnownNat (Length ns)
) => VEither es a -> VEither (Concat ns es) a
{-# INLINABLE veitherPrepend #-}
veitherPrepend = veitherBimap (prependVariant @ns) id
veitherAppend :: forall ns es a.
VEither es a -> VEither (Concat es ns) a
{-# INLINABLE veitherAppend #-}
veitherAppend = veitherBimap (appendVariant @ns) id
veitherCont :: (V es -> u) -> (a -> u) -> VEither es a -> u
{-# INLINABLE veitherCont #-}
veitherCont f g v = case v of
VLeft xs -> f xs
VRight x -> g x
veitherProduct :: KnownNat (Length (b:e2)) => VEither e1 a -> VEither e2 b -> VEither (Tail (Product (a:e1) (b:e2))) (a,b)
veitherProduct (VEither x) (VEither y) = VEither (productVariant x y)
instance Functor (VEither es) where
{-# INLINABLE fmap #-}
fmap f (VEither v) = VEither (mapVariantAt @0 f v)
instance Applicative (VEither es) where
pure = VRight
VRight f <*> VRight a = VRight (f a)
VLeft v <*> _ = VLeft v
_ <*> VLeft v = VLeft v
instance Monad (VEither es) where
VRight a >>= f = f a
VLeft v >>= _ = VLeft v
instance Foldable (VEither es) where
foldMap f (VRight a) = f a
foldMap _ (VLeft _) = mempty
instance Traversable (VEither es) where
traverse f (VRight a) = VRight <$> f a
traverse _ (VLeft xs) = pure (VLeft xs)