{-# 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 #-}
module Haskus.Utils.Variant
( V (..)
, variantIndex
, variantSize
, pattern V
, pattern VMaybe
, (:<)
, (:<<)
, (:<?)
, toVariantAt
, toVariantHead
, toVariantTail
, fromVariantAt
, fromVariantHead
, popVariantAt
, popVariantHead
, mapVariantAt
, mapVariantAtM
, foldMapVariantAt
, foldMapVariantAtM
, bindVariant
, constBindVariant
, variantHeadTail
, mapVariantHeadTail
, toVariant
, popVariant
, popVariantMaybe
, fromVariant
, fromVariantMaybe
, fromVariantFirst
, mapVariantFirst
, mapVariantFirstM
, mapVariant
, mapNubVariant
, foldMapVariantFirst
, foldMapVariantFirstM
, foldMapVariant
, Member
, Remove
, ReplaceAll
, MapVariant
, alterVariant
, traverseVariant
, traverseVariant_
, reduceVariant
, NoConstraint
, AlterVariant
, TraverseVariant
, ReduceVariant
, appendVariant
, prependVariant
, liftVariant
, nubVariant
, productVariant
, flattenVariant
, joinVariant
, joinVariantUnsafe
, splitVariant
, LiftVariant
, Flattenable
, FlattenVariant
, ExtractM
, JoinVariant
, SplitVariant
, variantToValue
, variantFromValue
, variantToEither
, variantFromEither
, variantToHList
, variantToTuple
, ContVariant (..)
, pattern VSilent
, liftVariant'
, fromVariant'
, popVariant'
, toVariant'
, LiftVariant'
, PopVariant
, showsVariant
)
where
import Unsafe.Coerce
import GHC.Exts (Any)
import Data.Typeable
import Control.DeepSeq
import Haskus.Utils.Monad
import Haskus.Utils.Types
import Haskus.Utils.Tuple
import Haskus.Utils.HList
import Haskus.Utils.ContFlow
data V (l :: [*]) = Variant {-# UNPACK #-} !Word Any
type role V representational
pattern V :: forall c cs. (c :< cs) => c -> V cs
pattern V x <- (fromVariant -> Just x)
where
V x = toVariant x
pattern VSilent :: forall c cs.
( Member c cs
, PopVariant c cs
) => c -> V cs
pattern VSilent x <- (fromVariant' -> Just x)
where
VSilent x = toVariant' x
pattern VMaybe :: forall c cs. (c :<? cs) => c -> V cs
pattern VMaybe x <- (fromVariantMaybe -> Just x)
instance Eq (V '[]) where
(==) _ _ = True
instance
( Eq (V xs)
, Eq x
) => Eq (V (x ': xs))
where
{-# INLINABLE (==) #-}
(==) v1@(Variant t1 _) v2@(Variant t2 _)
| t1 /= t2 = False
| otherwise = case (popVariantHead v1, popVariantHead v2) of
(Right a, Right b) -> a == b
(Left as, Left bs) -> as == bs
_ -> False
instance Ord (V '[]) where
compare = error "Empty variant"
instance
( Ord (V xs)
, Ord x
) => Ord (V (x ': xs))
where
compare v1 v2 = case (popVariantHead v1, popVariantHead v2) of
(Right a, Right b) -> compare a b
(Left as, Left bs) -> compare as bs
(Right _, Left _) -> LT
(Left _, Right _) -> GT
class ShowVariantValue a where
showVariantValue :: a -> ShowS
instance ShowVariantValue (V '[]) where
{-# INLINABLE showVariantValue #-}
showVariantValue _ = showString "undefined"
instance
( ShowVariantValue (V xs)
, Show x
, Typeable x
) => ShowVariantValue (V (x ': xs))
where
{-# INLINABLE showVariantValue #-}
showVariantValue v = case popVariantHead v of
Right x -> showString "V @"
. showsPrec 10 (typeOf x)
. showChar ' '
. showsPrec 11 x
Left xs -> showVariantValue xs
showsVariant ::
( Typeable xs
, ShowTypeList (V xs)
, ShowVariantValue (V xs)
) => Int -> V xs -> ShowS
showsVariant d v = showParen (d /= 0) $
showVariantValue v
. showString " :: "
. showString "V "
. showList__ (showTypeList v)
instance Show (V '[]) where
{-# INLINABLE showsPrec #-}
showsPrec _ _ = undefined
instance
( Show x
, Show (V xs)
) => Show (V (x ': xs))
where
showsPrec d v = case popVariantHead v of
Right x -> showsPrec d x
Left xs -> showsPrec d xs
showList__ :: [ShowS] -> ShowS
showList__ [] s = "'[]" ++ s
showList__ (x:xs) s = '\'' : '[' : x (showl xs)
where
showl [] = ']' : s
showl (y:ys) = ',' : ' ' : y (showl ys)
class ShowTypeList a where
showTypeList :: a -> [ShowS]
instance ShowTypeList (V '[]) where
{-# INLINABLE showTypeList #-}
showTypeList _ = []
instance (Typeable x, ShowTypeList (V xs)) => ShowTypeList (V (x ': xs)) where
{-# INLINABLE showTypeList #-}
showTypeList _ = showsPrec 0 (typeOf (undefined :: x)) : showTypeList (undefined :: V xs)
variantIndex :: V a -> Word
variantIndex (Variant n _) = n
variantSize :: forall xs. (KnownNat (Length xs)) => V xs -> Word
variantSize _ = natValue @(Length xs)
toVariantAt :: forall (n :: Nat) (l :: [*]).
( KnownNat n
) => Index n l -> V l
{-# INLINABLE toVariantAt #-}
toVariantAt a = Variant (natValue' @n) (unsafeCoerce a)
toVariantHead :: forall x xs. x -> V (x ': xs)
{-# INLINABLE toVariantHead #-}
toVariantHead a = Variant 0 (unsafeCoerce a)
toVariantTail :: forall x xs. V xs -> V (x ': xs)
{-# INLINABLE toVariantTail #-}
toVariantTail (Variant t a) = Variant (t+1) a
fromVariantAt :: forall (n :: Nat) (l :: [*]).
( KnownNat n
) => V l -> Maybe (Index n l)
{-# INLINABLE fromVariantAt #-}
fromVariantAt (Variant t a) = do
guard (t == natValue' @n)
return (unsafeCoerce a)
fromVariantHead :: V (x ': xs) -> Maybe x
{-# INLINABLE fromVariantHead #-}
fromVariantHead v = fromVariantAt @0 v
popVariantAt :: forall (n :: Nat) l.
( KnownNat n
) => V l -> Either (V (RemoveAt n l)) (Index n l)
{-# INLINABLE popVariantAt #-}
popVariantAt v@(Variant t a) = case fromVariantAt @n v of
Just x -> Right x
Nothing -> Left $ if t > natValue' @n
then Variant (t-1) a
else Variant t a
popVariantHead :: forall x xs. V (x ': xs) -> Either (V xs) x
{-# INLINABLE popVariantHead #-}
popVariantHead v@(Variant t a) = case fromVariantAt @0 v of
Just x -> Right x
Nothing -> Left $ Variant (t-1) a
mapVariantAt :: forall (n :: Nat) a b l.
( KnownNat n
, a ~ Index n l
) => (a -> b) -> V l -> V (ReplaceN n b l)
{-# INLINABLE mapVariantAt #-}
mapVariantAt f v@(Variant t a) =
case fromVariantAt @n v of
Nothing -> Variant t a
Just x -> Variant t (unsafeCoerce (f x))
mapVariantAtM :: forall (n :: Nat) a b l m .
( KnownNat n
, Applicative m
, a ~ Index n l
)
=> (a -> m b) -> V l -> m (V (ReplaceN n b l))
{-# INLINABLE mapVariantAtM #-}
mapVariantAtM f v@(Variant t a) =
case fromVariantAt @n v of
Nothing -> pure (Variant t a)
Just x -> Variant t <$> unsafeCoerce (f x)
bindVariant :: forall x xs ys.
( KnownNat (Length ys)
) => V (x ': xs) -> (x -> V ys) -> V (Concat ys xs)
{-# INLINABLE bindVariant #-}
v `bindVariant` f = case popVariantHead v of
Right x -> appendVariant @xs (f x)
Left xs -> prependVariant @ys xs
constBindVariant :: forall xs ys.
V xs -> V ys -> V (Concat ys xs)
{-# INLINABLE constBindVariant #-}
_ `constBindVariant` v2 = appendVariant @xs v2
variantHeadTail :: (x -> u) -> (V xs -> u) -> V (x ': xs) -> u
{-# INLINABLE variantHeadTail #-}
variantHeadTail fh ft x = case popVariantHead x of
Right h -> fh h
Left t -> ft t
mapVariantHeadTail :: (x -> y) -> (V xs -> V ys) -> V (x ': xs) -> V (y ': ys)
{-# INLINABLE mapVariantHeadTail #-}
mapVariantHeadTail fh ft x = case popVariantHead x of
Right h -> toVariantHead (fh h)
Left t -> toVariantTail (ft t)
toVariant :: forall a l.
( a :< l
) => a -> V l
{-# INLINABLE toVariant #-}
toVariant = toVariantAt @(IndexOf a l)
toVariant' :: forall a l.
( Member a l
) => a -> V l
{-# INLINABLE toVariant' #-}
toVariant' = toVariantAt @(IndexOf a l)
class PopVariant a xs where
popVariant' :: V xs -> Either (V (Remove a xs)) a
instance PopVariant a '[] where
{-# INLINABLE popVariant' #-}
popVariant' _ = undefined
instance forall a xs n xs' y ys.
( PopVariant a xs'
, n ~ MaybeIndexOf a xs
, xs' ~ RemoveAt1 n xs
, Remove a xs' ~ Remove a xs
, KnownNat n
, xs ~ (y ': ys)
) => PopVariant a (y ': ys)
where
{-# INLINABLE popVariant' #-}
popVariant' (Variant t a)
= case natValue' @n of
0 -> Left (Variant t a)
n | n-1 == t -> Right (unsafeCoerce a)
| n-1 < t -> popVariant' @a @xs' (Variant (t-1) a)
| otherwise -> Left (Variant t a)
class SplitVariant as rs xs where
splitVariant' :: V xs -> Either (V rs) (V as)
instance SplitVariant as rs '[] where
{-# INLINABLE splitVariant' #-}
splitVariant' _ = undefined
instance forall as rs xs x n m.
( n ~ MaybeIndexOf x as
, m ~ MaybeIndexOf x rs
, SplitVariant as rs xs
, KnownNat m
, KnownNat n
) => SplitVariant as rs (x ': xs)
where
{-# INLINABLE splitVariant' #-}
splitVariant' (Variant 0 v)
= case natValue' @n of
0 -> Left (Variant (natValue' @m - 1) v)
t -> Right (Variant (t-1) v)
splitVariant' (Variant t v)
= splitVariant' @as @rs (Variant (t-1) v :: V xs)
splitVariant :: forall as xs.
( SplitVariant as (Complement xs as) xs
) => V xs -> Either (V (Complement xs as)) (V as)
splitVariant = splitVariant' @as @(Complement xs as) @xs
type (:<) x xs =
( CheckMember x xs
, Member x xs
, x :<? xs
)
type family (:<<) xs ys :: Constraint where
'[] :<< ys = ()
(x ': xs) :<< ys = (x :< ys, xs :<< ys)
type (:<?) x xs =
( PopVariant x xs
)
popVariant :: forall a xs.
( a :< xs
) => V xs -> Either (V (Remove a xs)) a
{-# INLINABLE popVariant #-}
popVariant v = popVariant' @a v
popVariantMaybe :: forall a xs.
( a :<? xs
) => V xs -> Either (V (Remove a xs)) a
{-# INLINABLE popVariantMaybe #-}
popVariantMaybe v = popVariant' @a v
fromVariantFirst :: forall a l.
( Member a l
) => V l -> Maybe a
{-# INLINABLE fromVariantFirst #-}
fromVariantFirst = fromVariantAt @(IndexOf a l)
fromVariant :: forall a xs.
( a :< xs
) => V xs -> Maybe a
{-# INLINABLE fromVariant #-}
fromVariant v = case popVariant v of
Right a -> Just a
Left _ -> Nothing
fromVariant' :: forall a xs.
( PopVariant a xs
) => V xs -> Maybe a
{-# INLINABLE fromVariant' #-}
fromVariant' v = case popVariant' v of
Right a -> Just a
Left _ -> Nothing
fromVariantMaybe :: forall a xs.
( a :<? xs
) => V xs -> Maybe a
{-# INLINABLE fromVariantMaybe #-}
fromVariantMaybe v = case popVariantMaybe v of
Right a -> Just a
Left _ -> Nothing
mapVariantFirst :: forall a b n l.
( Member a l
, n ~ IndexOf a l
) => (a -> b) -> V l -> V (ReplaceN n b l)
{-# INLINABLE mapVariantFirst #-}
mapVariantFirst f v = mapVariantAt @n f v
mapVariantFirstM :: forall a b n l m.
( Member a l
, n ~ IndexOf a l
, Applicative m
) => (a -> m b) -> V l -> m (V (ReplaceN n b l))
{-# INLINABLE mapVariantFirstM #-}
mapVariantFirstM f v = mapVariantAtM @n f v
class MapVariantIndexes a b cs (is :: [Nat]) where
mapVariant' :: (a -> b) -> V cs -> V (ReplaceNS is b cs)
instance MapVariantIndexes a b '[] is where
{-# INLINABLE mapVariant' #-}
mapVariant' = undefined
instance MapVariantIndexes a b cs '[] where
{-# INLINABLE mapVariant' #-}
mapVariant' _ v = v
instance forall a b cs is i.
( MapVariantIndexes a b (ReplaceN i b cs) is
, a ~ Index i cs
, KnownNat i
) => MapVariantIndexes a b cs (i ': is) where
{-# INLINABLE mapVariant' #-}
mapVariant' f v = mapVariant' @a @b @(ReplaceN i b cs) @is f (mapVariantAt @i f v)
type MapVariant a b cs =
( MapVariantIndexes a b cs (IndexesOf a cs)
)
type ReplaceAll a b cs = ReplaceNS (IndexesOf a cs) b cs
mapVariant :: forall a b cs.
( MapVariant a b cs
) => (a -> b) -> V cs -> V (ReplaceAll a b cs)
{-# INLINABLE mapVariant #-}
mapVariant = mapVariant' @a @b @cs @(IndexesOf a cs)
mapNubVariant :: forall a b cs ds rs.
( MapVariant a b cs
, ds ~ ReplaceNS (IndexesOf a cs) b cs
, rs ~ Nub ds
, LiftVariant ds rs
) => (a -> b) -> V cs -> V rs
{-# INLINABLE mapNubVariant #-}
mapNubVariant f = nubVariant . mapVariant f
foldMapVariantAt :: forall (n :: Nat) l l2 .
( KnownNat n
, KnownNat (Length l2)
) => (Index n l -> V l2) -> V l -> V (ReplaceAt n l l2)
foldMapVariantAt f v@(Variant t a) =
case fromVariantAt @n v of
Nothing ->
if t < n
then Variant t a
else Variant (t+nl2-1) a
Just x -> case f x of
Variant t2 a2 -> Variant (t2+n) a2
where
n = natValue' @n
nl2 = natValue' @(Length l2)
foldMapVariantAtM :: forall (n :: Nat) m l l2.
( KnownNat n
, KnownNat (Length l2)
, Monad m
) => (Index n l -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2))
foldMapVariantAtM f v@(Variant t a) =
case fromVariantAt @n v of
Nothing ->
return $ if t < n
then Variant t a
else Variant (t+nl2-1) a
Just x -> do
y <- f x
case y of
Variant t2 a2 -> return (Variant (t2+n) a2)
where
n = natValue' @n
nl2 = natValue' @(Length l2)
foldMapVariantFirst :: forall a (n :: Nat) l l2 .
( KnownNat n
, KnownNat (Length l2)
, n ~ IndexOf a l
, a ~ Index n l
) => (a -> V l2) -> V l -> V (ReplaceAt n l l2)
foldMapVariantFirst f v = foldMapVariantAt @n f v
foldMapVariantFirstM :: forall a (n :: Nat) l l2 m.
( KnownNat n
, KnownNat (Length l2)
, n ~ IndexOf a l
, a ~ Index n l
, Monad m
) => (a -> m (V l2)) -> V l -> m (V (ReplaceAt n l l2))
foldMapVariantFirstM f v = foldMapVariantAtM @n f v
foldMapVariant :: forall a cs ds i.
( i ~ IndexOf a cs
, a :< cs
) => (a -> V ds) -> V cs -> V (InsertAt i (Remove a cs) ds)
foldMapVariant f v = case popVariant v of
Right a -> case f a of
Variant t x -> Variant (i + t) x
Left (Variant t x)
| t < i -> Variant t x
| otherwise -> Variant (i+t) x
where
i = natValue' @i
class NoConstraint a
instance NoConstraint a
class AlterVariant c (b :: [*]) where
alterVariant' :: (forall a. c a => a -> a) -> Word -> Any -> Any
instance AlterVariant c '[] where
{-# INLINABLE alterVariant' #-}
alterVariant' _ = undefined
instance
( AlterVariant c xs
, c x
) => AlterVariant c (x ': xs)
where
{-# INLINABLE alterVariant' #-}
alterVariant' f t v =
case t of
0 -> unsafeCoerce (f (unsafeCoerce v :: x))
n -> alterVariant' @c @xs f (n-1) v
alterVariant :: forall c (a :: [*]).
( AlterVariant c a
) => (forall x. c x => x -> x) -> V a -> V a
{-# INLINABLE alterVariant #-}
alterVariant f (Variant t a) =
Variant t (alterVariant' @c @a f t a)
class TraverseVariant c (b :: [*]) m where
traverseVariant' :: (forall a . (Monad m, c a) => a -> m a) -> Word -> Any -> m Any
instance TraverseVariant c '[] m where
{-# INLINABLE traverseVariant' #-}
traverseVariant' _ = undefined
instance
( TraverseVariant c xs m
, c x
, Monad m
) => TraverseVariant c (x ': xs) m
where
{-# INLINABLE traverseVariant' #-}
traverseVariant' f t v =
case t of
0 -> unsafeCoerce <$> f (unsafeCoerce v :: x)
n -> traverseVariant' @c @xs f (n-1) v
traverseVariant :: forall c (a :: [*]) m.
( TraverseVariant c a m
, Monad m
) => (forall x. c x => x -> m x) -> V a -> m (V a)
{-# INLINABLE traverseVariant #-}
traverseVariant f (Variant t a) =
Variant t <$> traverseVariant' @c @a f t a
traverseVariant_ :: forall c (a :: [*]) m.
( TraverseVariant c a m
, Monad m
) => (forall x. c x => x -> m ()) -> V a -> m ()
{-# INLINABLE traverseVariant_ #-}
traverseVariant_ f v = void (traverseVariant @c @a f' v)
where
f' :: forall x. c x => x -> m x
f' x = f x >> return x
class ReduceVariant c (b :: [*]) where
reduceVariant' :: (forall a. c a => a -> r) -> Word -> Any -> r
instance ReduceVariant c '[] where
{-# INLINABLE reduceVariant' #-}
reduceVariant' _ = undefined
instance
( ReduceVariant c xs
, c x
) => ReduceVariant c (x ': xs)
where
{-# INLINABLE reduceVariant' #-}
reduceVariant' f t v =
case t of
0 -> f (unsafeCoerce v :: x)
n -> reduceVariant' @c @xs f (n-1) v
reduceVariant :: forall c (a :: [*]) r.
( ReduceVariant c a
) => (forall x. c x => x -> r) -> V a -> r
{-# INLINABLE reduceVariant #-}
reduceVariant f (Variant t a) = reduceVariant' @c @a f t a
appendVariant :: forall (ys :: [*]) (xs :: [*]). V xs -> V (Concat xs ys)
{-# INLINABLE appendVariant #-}
appendVariant (Variant t a) = Variant t a
prependVariant :: forall (ys :: [*]) (xs :: [*]).
( KnownNat (Length ys)
) => V xs -> V (Concat ys xs)
{-# INLINABLE prependVariant #-}
prependVariant (Variant t a) = Variant (n+t) a
where
n = natValue' @(Length ys)
type LiftVariant xs ys =
( LiftVariant' xs ys
, xs :<< ys
)
class LiftVariant' xs ys where
liftVariant' :: V xs -> V ys
instance LiftVariant' '[] ys where
{-# INLINABLE liftVariant' #-}
liftVariant' _ = undefined
instance forall xs ys x.
( LiftVariant' xs ys
, KnownNat (IndexOf x ys)
) => LiftVariant' (x ': xs) ys
where
{-# INLINABLE liftVariant' #-}
liftVariant' (Variant t a)
| t == 0 = Variant (natValue' @(IndexOf x ys)) a
| otherwise = liftVariant' @xs (Variant (t-1) a)
liftVariant :: forall ys xs.
( LiftVariant xs ys
) => V xs -> V ys
{-# INLINABLE liftVariant #-}
liftVariant = liftVariant'
nubVariant :: (LiftVariant xs (Nub xs)) => V xs -> V (Nub xs)
{-# INLINABLE nubVariant #-}
nubVariant = liftVariant
productVariant :: forall xs ys.
( KnownNat (Length ys)
) => V xs -> V ys -> V (Product xs ys)
{-# INLINABLE productVariant #-}
productVariant (Variant n1 a1) (Variant n2 a2)
= Variant (n1 * natValue @(Length ys) + n2) (unsafeCoerce (a1,a2))
type family FlattenVariant (xs :: [*]) :: [*] where
FlattenVariant '[] = '[]
FlattenVariant (V xs:ys) = Concat xs (FlattenVariant ys)
FlattenVariant (y:ys) = y ': FlattenVariant ys
class Flattenable a rs where
toFlattenVariant :: Word -> a -> rs
instance Flattenable (V '[]) rs where
{-# INLINABLE toFlattenVariant #-}
toFlattenVariant _ _ = undefined
instance forall xs ys rs.
( Flattenable (V ys) (V rs)
, KnownNat (Length xs)
) => Flattenable (V (V xs ': ys)) (V rs)
where
{-# INLINABLE toFlattenVariant #-}
toFlattenVariant i v = case popVariantHead v of
Right (Variant n a) -> Variant (i+n) a
Left vys -> toFlattenVariant (i+natValue @(Length xs)) vys
flattenVariant :: forall xs.
( Flattenable (V xs) (V (FlattenVariant xs))
) => V xs -> V (FlattenVariant xs)
{-# INLINABLE flattenVariant #-}
flattenVariant v = toFlattenVariant 0 v
type family ExtractM m f where
ExtractM m '[] = '[]
ExtractM m (m x ': xs) = x ': ExtractM m xs
class JoinVariant m xs where
joinVariant :: V xs -> m (V (ExtractM m xs))
instance JoinVariant m '[] where
{-# INLINABLE joinVariant #-}
joinVariant _ = undefined
instance forall m xs a.
( Functor m
, ExtractM m (m a ': xs) ~ (a ': ExtractM m xs)
, JoinVariant m xs
) => JoinVariant m (m a ': xs) where
{-# INLINABLE joinVariant #-}
joinVariant (Variant 0 a) = (Variant 0 . unsafeCoerce) <$> (unsafeCoerce a :: m a)
joinVariant (Variant n a) = prependVariant @'[a] <$> joinVariant (Variant (n-1) a :: V xs)
joinVariantUnsafe :: forall m xs ys.
( Functor m
, ys ~ ExtractM m xs
) => V xs -> m (V ys)
{-# INLINABLE joinVariantUnsafe #-}
joinVariantUnsafe (Variant t act) = Variant t <$> (unsafeCoerce act :: m Any)
instance NFData (V '[]) where
{-# INLINABLE rnf #-}
rnf _ = ()
instance (NFData x, NFData (V xs)) => NFData (V (x ': xs)) where
{-# INLINABLE rnf #-}
rnf v = case popVariantHead v of
Right x -> rnf x
Left xs -> rnf xs
variantToValue :: V '[a] -> a
{-# INLINABLE variantToValue #-}
variantToValue (Variant _ a) = unsafeCoerce a
variantFromValue :: a -> V '[a]
{-# INLINABLE variantFromValue #-}
variantFromValue a = Variant 0 (unsafeCoerce a)
variantToEither :: forall a b. V '[a,b] -> Either b a
{-# INLINABLE variantToEither #-}
variantToEither (Variant 0 a) = Right (unsafeCoerce a)
variantToEither (Variant _ a) = Left (unsafeCoerce a)
variantFromEither :: Either a b -> V '[b,a]
{-# INLINABLE variantFromEither #-}
variantFromEither (Left a) = toVariantAt @1 a
variantFromEither (Right b) = toVariantAt @0 b
class VariantToHList xs where
variantToHList :: V xs -> HList (Map Maybe xs)
instance VariantToHList '[] where
variantToHList _ = HNil
instance
( VariantToHList xs
) => VariantToHList (x ': xs)
where
variantToHList v@(Variant t a) =
fromVariantAt @0 v `HCons` variantToHList v'
where
v' :: V xs
v' = Variant (t-1) a
variantToTuple :: forall l t.
( VariantToHList l
, HTuple (Map Maybe l)
, t ~ Tuple (Map Maybe l)
) => V l -> t
variantToTuple = hToTuple . variantToHList
instance ContVariant xs => MultiCont (V xs) where
type MultiContTypes (V xs) = xs
toCont = variantToCont
toContM = variantToContM
class ContVariant xs where
variantToCont :: V xs -> ContFlow xs r
variantToContM :: Monad m => m (V xs) -> ContFlow xs (m r)
contToVariant :: ContFlow xs (V xs) -> V xs
contToVariantM :: Monad m => ContFlow xs (m (V xs)) -> m (V xs)
instance ContVariant '[a] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant _ a) = ContFlow $ \(Unit f) ->
f (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(Unit f) -> do
Variant _ a <- act
f (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
Unit (toVariantAt @0)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
Unit (return . toVariantAt @0)
instance ContVariant '[a,b] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2) ->
case t of
0 -> f1 (unsafeCoerce a)
_ -> f2 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
_ -> f2 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
)
instance ContVariant '[a,b,c] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
_ -> f3 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
_ -> f3 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
)
instance ContVariant '[a,b,c,d] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
_ -> f4 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
_ -> f4 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
)
instance ContVariant '[a,b,c,d,e] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
_ -> f5 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
_ -> f5 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
)
instance ContVariant '[a,b,c,d,e,f] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
_ -> f6 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
_ -> f6 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
)
instance ContVariant '[a,b,c,d,e,f,g] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
_ -> f7 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
_ -> f7 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
)
instance ContVariant '[a,b,c,d,e,f,g,h] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
_ -> f8 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
_ -> f8 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
, toVariantAt @7
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
, return . toVariantAt @7
)
instance ContVariant '[a,b,c,d,e,f,g,h,i] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
_ -> f9 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
_ -> f9 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
, toVariantAt @7
, toVariantAt @8
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
, return . toVariantAt @7
, return . toVariantAt @8
)
instance ContVariant '[a,b,c,d,e,f,g,h,i,j] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
_ -> f10 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
_ -> f10 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
, toVariantAt @7
, toVariantAt @8
, toVariantAt @9
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
, return . toVariantAt @7
, return . toVariantAt @8
, return . toVariantAt @9
)
instance ContVariant '[a,b,c,d,e,f,g,h,i,j,k] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
9 -> f10 (unsafeCoerce a)
_ -> f11 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
9 -> f10 (unsafeCoerce a)
_ -> f11 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
, toVariantAt @7
, toVariantAt @8
, toVariantAt @9
, toVariantAt @10
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
, return . toVariantAt @7
, return . toVariantAt @8
, return . toVariantAt @9
, return . toVariantAt @10
)
instance ContVariant '[a,b,c,d,e,f,g,h,i,j,k,l] where
{-# INLINABLE variantToCont #-}
variantToCont (Variant t a) = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12) ->
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
9 -> f10 (unsafeCoerce a)
10 -> f11 (unsafeCoerce a)
_ -> f12 (unsafeCoerce a)
{-# INLINABLE variantToContM #-}
variantToContM act = ContFlow $ \(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12) -> do
Variant t a <- act
case t of
0 -> f1 (unsafeCoerce a)
1 -> f2 (unsafeCoerce a)
2 -> f3 (unsafeCoerce a)
3 -> f4 (unsafeCoerce a)
4 -> f5 (unsafeCoerce a)
5 -> f6 (unsafeCoerce a)
6 -> f7 (unsafeCoerce a)
7 -> f8 (unsafeCoerce a)
8 -> f9 (unsafeCoerce a)
9 -> f10 (unsafeCoerce a)
10 -> f11 (unsafeCoerce a)
_ -> f12 (unsafeCoerce a)
{-# INLINABLE contToVariant #-}
contToVariant c = c >::>
( toVariantAt @0
, toVariantAt @1
, toVariantAt @2
, toVariantAt @3
, toVariantAt @4
, toVariantAt @5
, toVariantAt @6
, toVariantAt @7
, toVariantAt @8
, toVariantAt @9
, toVariantAt @10
, toVariantAt @11
)
{-# INLINABLE contToVariantM #-}
contToVariantM c = c >::>
( return . toVariantAt @0
, return . toVariantAt @1
, return . toVariantAt @2
, return . toVariantAt @3
, return . toVariantAt @4
, return . toVariantAt @5
, return . toVariantAt @6
, return . toVariantAt @7
, return . toVariantAt @8
, return . toVariantAt @9
, return . toVariantAt @10
, return . toVariantAt @11
)