diff --git a/haskus-utils-variant.cabal b/haskus-utils-variant.cabal
--- a/haskus-utils-variant.cabal
+++ b/haskus-utils-variant.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.20
 name: haskus-utils-variant
-version: 2.0.3
+version: 2.1
 license: BSD3
 license-file: LICENSE
 copyright: Sylvain Henry 2018
@@ -25,6 +25,7 @@
         Haskus.Utils.Variant.Flow
         Haskus.Utils.Variant.Cont
         Haskus.Utils.Variant.Syntax
+        Haskus.Utils.VariantF
         Haskus.Utils.EADT
         Haskus.Utils.EADT.TH
     hs-source-dirs: src/lib
@@ -33,7 +34,7 @@
     build-depends:
         base >=4.9 && <4.12,
         template-haskell >=2.13.0.0 && <2.14,
-        haskus-utils-types ==1.1.*,
+        haskus-utils-types ==1.2.*,
         haskus-utils-data ==1.1.*
 
 test-suite tests
diff --git a/src/lib/Haskus/Utils/EADT.hs b/src/lib/Haskus/Utils/EADT.hs
--- a/src/lib/Haskus/Utils/EADT.hs
+++ b/src/lib/Haskus/Utils/EADT.hs
@@ -8,37 +8,13 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE PatternSynonyms #-}
-{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
 
 -- | Extensible ADT
 module Haskus.Utils.EADT
-   ( VariantF (..)
-   , ApplyAll
-   , pattern FV
-   , appendVariantF
-   , toVariantFHead
-   , toVariantFTail
-   , popVariantFHead
-   , popVariantF
-   , mapVariantF
-   , variantFToValue
-   , LiftableF
-   , liftVariantF
-   , AlterVariantF
-   , alterVariantF
-   , AlgVariantF
-   , algVariantF
-   , splitVariantF
-   , variantFToCont
-   , variantFToContM
-   , contToVariantF
-   , contToVariantFM
-   -- * Extensible ADT
-   , EADT
+   ( EADT
    , (:<:)
    , (:<<:)
    , pattern VF
@@ -54,222 +30,19 @@
    , contToEADT
    , contToEADTM
    -- * Reexport
-   , NoConstraint
    , module Haskus.Utils.Functor
+   , module Haskus.Utils.VariantF
    )
 where
 
+import Haskus.Utils.VariantF
 import Haskus.Utils.Variant
 import Haskus.Utils.Functor
 import Haskus.Utils.Types.List
 import Haskus.Utils.Types
 import Haskus.Utils.ContFlow
 
-import Unsafe.Coerce
-import Data.Bifunctor
-import GHC.Exts (Any,Constraint)
-
--- | Recursive Functor-like Variant
-newtype VariantF (xs :: [* -> *]) e
-   = VariantF (V (ApplyAll e xs))
-
--- | Apply its first argument to every element of the 2nd arg list
---
--- > ApplyAll e '[f,g,h] ==> '[f e, g e, h e]
---
-type family ApplyAll e (xs :: [* -> *]) :: [*] where
-   ApplyAll e '[]       = '[]
-   ApplyAll e (f ': fs) = f e ': ApplyAll e fs
-
-instance (Show (V (ApplyAll e xs))) => Show (VariantF xs e) where
-   show (VariantF x) = show x
-deriving instance (Eq (V (ApplyAll e xs))) => Eq (VariantF xs e)
-deriving instance (Ord (V (ApplyAll e xs))) => Ord (VariantF xs e)
-
-instance Functor (VariantF '[]) where
-   fmap _ = undefined
-
-instance (Functor (VariantF fs), Functor f) => Functor (VariantF (f ': fs)) where
-   fmap f (VariantF v) = case popVariantHead v of
-      Right x -> toVariantFHead (fmap f x)
-      Left xs -> toVariantFTail (fmap f (VariantF xs))
-
--- | Pattern-match in a VariantF
-pattern FV :: forall c cs e. c :< (ApplyAll e cs) => c -> VariantF cs e
-pattern FV x = VariantF (V x)
-
--- | Retrieve a single value
-variantFToValue :: VariantF '[f] e -> f e
-variantFToValue (VariantF v) = variantToValue v
-
-appendVariantF :: forall (ys :: [* -> *]) (xs :: [* -> *]) e.
-   ( ApplyAll e (Concat xs ys) ~ Concat (ApplyAll e xs) (ApplyAll e ys)
-   ) => VariantF xs e -> VariantF (Concat xs ys) e
-appendVariantF (VariantF v) = VariantF (appendVariant @(ApplyAll e ys) v)
-
--- | Set the first value
-toVariantFHead :: forall x xs e. x e -> VariantF (x ': xs) e
-{-# INLINE toVariantFHead #-}
-toVariantFHead v = VariantF (toVariantHead @(x e) @(ApplyAll e xs) v)
-
--- | Set the tail
-toVariantFTail :: forall x xs e. VariantF xs e -> VariantF (x ': xs) e
-{-# INLINE toVariantFTail #-}
-toVariantFTail (VariantF v) = VariantF (toVariantTail @(x e) @(ApplyAll e xs) v)
-
--- | Pop VariantF head
-popVariantFHead :: forall x xs e. VariantF (x ': xs) e -> Either (VariantF xs e) (x e)
-{-# INLINE popVariantFHead #-}
-popVariantFHead (VariantF v) = case popVariantHead v of
-   Right x -> Right x
-   Left xs -> Left (VariantF xs)
-
--- | Pop VariantF
-popVariantF :: forall x xs ys e.
-   ( x e :< ApplyAll e xs
-   , Filter (x e) (ApplyAll e xs) ~ ApplyAll e ys
-   ) => VariantF xs e -> Either (VariantF ys e) (x e)
-{-# INLINE popVariantF #-}
-popVariantF (VariantF v) = case popVariant v of
-   Right x -> Right x
-   Left xs -> Left (VariantF xs)
-
--- | Map the matching types of a variant
-mapVariantF :: forall a b cs e ds as.
-   ( MapVariant (a e) (b e) as
-   , ds ~ ReplaceNS (IndexesOf a cs) b cs
-   , as ~ ApplyAll e cs
-   , ApplyAll e ds ~ ReplaceNS (IndexesOf (a e) as) (b e) as
-   ) => (a e -> b e) -> VariantF cs e -> VariantF ds e
-mapVariantF f (VariantF v) = VariantF (mapVariant @(a e) @(b e) @as f v)
-
--- | xs is liftable in ys
-type LiftableF e xs ys =
-   ( IsSubset xs ys ~ 'True
-   , LiftVariant (ApplyAll e xs) (ApplyAll e ys)
-   )
-
--- | Lift a VariantF into another
-liftVariantF :: forall e as bs.
-   ( LiftableF e as bs
-   ) => VariantF as e -> VariantF bs e
-liftVariantF (VariantF v) = VariantF (liftVariant' v)
-
-class AlterVariantF (c :: (* -> *) -> Constraint) e (xs :: [* -> *]) where
-   alterVariantF' :: (forall (f :: * -> *). c f => f e -> f e) -> Word -> Any -> Any
-
-instance AlterVariantF c e '[] where
-   {-# INLINE alterVariantF' #-}
-   alterVariantF' _ = undefined
-
-instance
-   ( AlterVariantF c e xs
-   , c x
-   ) => AlterVariantF c e (x ': xs)
-   where
-      {-# INLINE alterVariantF' #-}
-      alterVariantF' f t v =
-         case t of
-            0 -> unsafeCoerce (f (unsafeCoerce v :: x e))
-            n -> alterVariantF' @c @e @xs f (n-1) v
-
--- | Alter a variant. You need to specify the constraints required by the
--- modifying function.
---
--- Usage:
---
--- >   alterVariantF @NoConstraint id         v
--- >   alterVariantF @Resizable    (resize 4) v
--- >
--- >   -- Multiple constraints:
--- >   class (Ord a, Num a) => OrdNum a
--- >   instance (Ord a, Num a) => OrdNum a
--- >   alterVariantF @OrdNum foo v
---
-alterVariantF :: forall c e (xs :: [* -> *]).
-   ( AlterVariantF c e xs
-   ) => (forall (f :: * -> *). c f => f e -> f e) -> VariantF xs e -> VariantF xs e
-{-# INLINABLE alterVariantF #-}
-alterVariantF f (VariantF (Variant t a)) =
-   VariantF (Variant t (alterVariantF' @c @e @xs f t a))
-
-
-class AlgVariantF (c :: (* -> *) -> Constraint) e (xs :: [* -> *]) where
-   algVariantF' :: (forall (f :: * -> *). c f => f e -> e) -> Word -> Any -> e
-
-instance AlgVariantF c e '[] where
-   {-# INLINE algVariantF' #-}
-   algVariantF' _ = undefined
-
-instance
-   ( AlgVariantF c e xs
-   , c x
-   ) => AlgVariantF c e (x ': xs)
-   where
-      {-# INLINE algVariantF' #-}
-      algVariantF' f t v =
-         case t of
-            0 -> f (unsafeCoerce v :: x e)
-            n -> algVariantF' @c @e @xs f (n-1) v
-
--- | Apply an algebra to a VariantF. You need to specify the constraints
--- required by the modifying function.
---
--- Usage:
---
--- >  algVariantF @NoConstraint id         v
--- >  algVariantF @Resizable    (resize 4) v
---
-algVariantF :: forall c e (xs :: [* -> *]).
-   ( AlgVariantF c e xs
-   ) => (forall (f :: * -> *). c f => f e -> e) -> VariantF xs e -> e
-{-# INLINABLE algVariantF #-}
-algVariantF f (VariantF (Variant t a)) = algVariantF' @c @e @xs f t a
-
-
--- | Split a VariantF in two
-splitVariantF :: forall as xs e.
-   ( Complement (ApplyAll e xs) (ApplyAll e as) ~ ApplyAll e (Complement xs as)
-   , SplitVariant (ApplyAll e as) (ApplyAll e xs) (ApplyAll e xs)
-   ) => VariantF xs e
-     -> Either (VariantF as e) (VariantF (Complement xs as) e)
-splitVariantF (VariantF v) = bimap VariantF VariantF (splitVariant v)
-
--- | Convert a VariantF into a multi-continuation
-variantFToCont :: ContVariant (ApplyAll e xs)
-   => VariantF xs e -> ContFlow (ApplyAll e xs) r
-variantFToCont (VariantF v) = variantToCont v
-
--- | Convert a VariantF into a multi-continuation
-variantFToContM ::
-   ( ContVariant (ApplyAll e xs)
-   , Monad m
-   ) => m (VariantF xs e) -> ContFlow (ApplyAll e xs) (m r)
-variantFToContM f = variantToContM (unvariantF <$> f)
-   where
-      unvariantF (VariantF v) = v
-
--- | Convert a multi-continuation into a VariantF
-contToVariantF :: forall xs e.
-   ( ContVariant (ApplyAll e xs)
-   ) => ContFlow (ApplyAll e xs) (V (ApplyAll e xs)) -> VariantF xs e
-contToVariantF c = VariantF (contToVariant c)
-
--- | Convert a multi-continuation into a VariantF
-contToVariantFM :: forall xs e m.
-   ( ContVariant (ApplyAll e xs)
-   , Monad m
-   ) => ContFlow (ApplyAll e xs) (m (V (ApplyAll e xs))) -> m (VariantF xs e)
-contToVariantFM f = VariantF <$> contToVariantM f
-
-instance ContVariant (ApplyAll e xs) => MultiCont (VariantF xs e) where
-   type MultiContTypes (VariantF xs e) = ApplyAll e xs
-   toCont = variantFToCont
-   toContM = variantFToContM
-
---------------------------------------------
--- Extensible ADT
---------------------------------------------
+import GHC.Exts (Constraint)
 
 -- | An extensible ADT
 type EADT xs = Fix (VariantF xs)
@@ -288,6 +61,7 @@
    , Index (IndexOf (f e) (ApplyAll e cs)) (ApplyAll e cs) ~ f e
    , PopVariant (f e) (ApplyAll e cs)
    , KnownNat (IndexOf (f e) (ApplyAll e cs))
+   , Remove (f e) (ApplyAll e cs) ~ ApplyAll e (Remove f cs)
    )
 
 -- | Pattern-match in an extensible ADT
@@ -310,7 +84,7 @@
 -- | Lift an EADT into another
 liftEADT :: forall e as bs.
    ( e ~ Fix (VariantF bs)
-   , LiftableF e as bs
+   , LiftVariantF e as bs
    , Functor (VariantF as)
    ) => EADT as -> EADT bs
 liftEADT = cata (Fix . liftVariantF)
@@ -320,8 +94,7 @@
    ( f :<: xs
    , e ~ EADT xs
    , f e :< ApplyAll e xs
-   , Filter (f e) (ApplyAll e xs) ~ ApplyAll e (Filter f xs)
-   ) => EADT xs -> Either (VariantF (Filter f xs) (EADT xs)) (f (EADT xs))
+   ) => EADT xs -> Either (VariantF (Remove f xs) (EADT xs)) (f (EADT xs))
 popEADT (Fix v) = popVariantF v
 
 type AlterEADT c xs = AlterVariantF c (EADT xs) xs
diff --git a/src/lib/Haskus/Utils/Variant.hs b/src/lib/Haskus/Utils/Variant.hs
--- a/src/lib/Haskus/Utils/Variant.hs
+++ b/src/lib/Haskus/Utils/Variant.hs
@@ -42,7 +42,7 @@
    -- * Operations by type
    , toVariant
    , Member
-   , Filter
+   , Remove
    , popVariant
    , popVariantMaybe
    , fromVariant
@@ -69,7 +69,7 @@
    -- * Conversions between variants
    , appendVariant
    , prependVariant
-   , Liftable
+   , LiftVariant
    , liftVariant
    , nubVariant
    , productVariant
@@ -97,7 +97,7 @@
    , fromVariant'
    , popVariant'
    , toVariant'
-   , LiftVariant
+   , LiftVariant'
    , PopVariant
    )
 where
@@ -312,7 +312,7 @@
 
 class PopVariant a xs where
    -- | Remove a type from a variant
-   popVariant' :: V xs -> Either (V (Filter a xs)) a
+   popVariant' :: V xs -> Either (V (Remove a xs)) a
 
 instance PopVariant a '[] where
    {-# INLINE popVariant' #-}
@@ -322,7 +322,7 @@
       ( PopVariant a xs'
       , n ~ MaybeIndexOf a xs
       , xs' ~ RemoveAt1 n xs
-      , Filter a xs' ~ Filter a xs
+      , Remove a xs' ~ Remove a xs
       , KnownNat n
       , xs ~ (y ': ys)
       ) => PopVariant a (y ': ys)
@@ -385,7 +385,7 @@
 -- remaining variant
 popVariant :: forall a xs.
    ( a :< xs
-   ) => V xs -> Either (V (Filter a xs)) a
+   ) => V xs -> Either (V (Remove a xs)) a
 {-# INLINABLE popVariant #-}
 popVariant v = popVariant' @a v
 
@@ -393,7 +393,7 @@
 -- remaining variant
 popVariantMaybe :: forall a xs.
    ( a :<? xs
-   ) => V xs -> Either (V (Filter a xs)) a
+   ) => V xs -> Either (V (Remove a xs)) a
 {-# INLINABLE popVariantMaybe #-}
 popVariantMaybe v = popVariant' @a v
 
@@ -489,7 +489,7 @@
    ( MapVariant a b cs
    , ds ~ ReplaceNS (IndexesOf a cs) b cs
    , rs ~ Nub ds
-   , Liftable ds rs
+   , LiftVariant ds rs
    ) => (a -> b) -> V cs -> V rs
 {-# INLINABLE mapNubVariant #-}
 mapNubVariant f = nubVariant . mapVariant f
@@ -561,7 +561,7 @@
 foldMapVariant :: forall a cs ds i.
    ( i ~ IndexOf a cs
    , a :< cs
-   ) => (a -> V ds) -> V cs -> V (InsertAt i (Filter a cs) ds)
+   ) => (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
@@ -717,22 +717,22 @@
       n = natValue' @(Length ys)
 
 -- | xs is liftable in ys
-type Liftable xs ys =
+type LiftVariant xs ys =
    ( IsSubset xs ys ~ 'True
-   , LiftVariant xs ys
+   , LiftVariant' xs ys
    )
 
-class LiftVariant xs ys where
+class LiftVariant' xs ys where
    liftVariant' :: V xs -> V ys
 
-instance LiftVariant '[] ys where
+instance LiftVariant' '[] ys where
    {-# INLINE liftVariant' #-}
    liftVariant' _ = undefined
 
 instance forall xs ys x.
-      ( LiftVariant xs ys
+      ( LiftVariant' xs ys
       , KnownNat (IndexOf x ys)
-      ) => LiftVariant (x ': xs) ys
+      ) => LiftVariant' (x ': xs) ys
    where
       {-# INLINE liftVariant' #-}
       liftVariant' (Variant t a)
@@ -744,13 +744,13 @@
 --
 -- Set values to the first matching type
 liftVariant :: forall ys xs.
-   ( Liftable xs ys
+   ( LiftVariant xs ys
    ) => V xs -> V ys
 {-# INLINABLE liftVariant #-}
 liftVariant = liftVariant'
 
 -- | Nub the type list
-nubVariant :: (Liftable xs (Nub xs)) => V xs -> V (Nub xs)
+nubVariant :: (LiftVariant xs (Nub xs)) => V xs -> V (Nub xs)
 {-# INLINABLE nubVariant #-}
 nubVariant = liftVariant
 
diff --git a/src/lib/Haskus/Utils/Variant/Flow.hs b/src/lib/Haskus/Utils/Variant/Flow.hs
--- a/src/lib/Haskus/Utils/Variant/Flow.hs
+++ b/src/lib/Haskus/Utils/Variant/Flow.hs
@@ -25,7 +25,7 @@
    , flowFor
    , flowTraverseFilter
    , flowForFilter
-   , Liftable
+   , LiftVariant
    , (:<)
    , (:<?)
    -- * Functor, applicative equivalents
@@ -225,7 +225,7 @@
 flowSingle = flowSetN @0
 
 -- | Lift a flow into another
-flowLift :: (Liftable xs ys , Monad m) => Flow m xs -> Flow m ys
+flowLift :: (LiftVariant xs ys , Monad m) => Flow m xs -> Flow m ys
 {-# INLINABLE flowLift #-}
 flowLift = fmap liftVariant
 
@@ -296,8 +296,8 @@
 
 -- | Bind two flows in a monadish way (error types union)
 flowBind :: forall xs ys zs m x.
-   ( Liftable xs zs
-   , Liftable ys zs
+   ( LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    , Monad m
    ) => Flow m (x ': ys) -> (x -> Flow m xs) -> Flow m zs
@@ -313,7 +313,7 @@
 flowMatch :: forall x xs zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
+   , LiftVariant (Remove x xs) zs
    ) => Flow m xs -> (x -> Flow m zs) -> Flow m zs
 {-# INLINABLE flowMatch #-}
 flowMatch = (>%~^>)
@@ -322,7 +322,7 @@
 flowMatchFail :: forall x xs m.
    ( Monad m
    , x :< xs
-   ) => Flow m xs -> (x -> m ()) -> Flow m (Filter x xs)
+   ) => Flow m xs -> (x -> m ()) -> Flow m (Remove x xs)
 {-# INLINABLE flowMatchFail #-}
 flowMatchFail = (>%~!!>)
 
@@ -373,8 +373,8 @@
 -- | Extract the first value, lift both
 (.~^^>) :: forall m a xs ys zs.
    ( Monad m
-   , Liftable xs zs
-   , Liftable ys zs
+   , LiftVariant xs zs
+   , LiftVariant ys zs
    ) => V (a ': ys) -> (a -> Flow m xs) -> Flow m zs
 {-# INLINABLE (.~^^>) #-}
 (.~^^>) v f = makeFlowOp selectFirst (applyF f) combineLiftBoth v
@@ -385,8 +385,8 @@
 -- | Extract the first value, lift both
 (>.~^^>) :: forall m a xs ys zs.
    ( Monad m
-   , Liftable xs zs
-   , Liftable ys zs
+   , LiftVariant xs zs
+   , LiftVariant ys zs
    ) => Flow m (a ': ys) -> (a -> Flow m xs) -> Flow m zs
 {-# INLINABLE (>.~^^>) #-}
 (>.~^^>) = liftm (.~^^>)
@@ -396,7 +396,7 @@
 -- | Extract the first value, lift unselected
 (.~^>) :: forall m a ys zs.
    ( Monad m
-   , Liftable ys zs
+   , LiftVariant ys zs
    ) => V (a ': ys) -> (a -> Flow m zs) -> Flow m zs
 {-# INLINABLE (.~^>) #-}
 (.~^>) v f = makeFlowOp selectFirst (applyF f) combineLiftUnselected v
@@ -406,7 +406,7 @@
 -- | Extract the first value, lift unselected
 (>.~^>) :: forall m a ys zs.
    ( Monad m
-   , Liftable ys zs
+   , LiftVariant ys zs
    ) => Flow m (a ': ys) -> (a -> Flow m zs) -> Flow m zs
 {-# INLINABLE (>.~^>) #-}
 (>.~^>) = liftm (.~^>)
@@ -433,8 +433,8 @@
 
 -- | Take the first output, union the result
 (.~|>) ::
-   ( Liftable xs zs
-   , Liftable ys zs
+   ( LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    , Monad m
    ) => V (a ': ys) -> (a -> Flow m xs) -> Flow m zs
@@ -445,8 +445,8 @@
 
 -- | Take the first output, fusion the result
 (>.~|>) ::
-   ( Liftable xs zs
-   , Liftable ys zs
+   ( LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    , Monad m
    ) => Flow m (a ': ys) -> (a -> Flow m xs) -> Flow m zs
@@ -580,8 +580,8 @@
 -- | Applicative <*> equivalent, with error union
 (<|<) :: forall m xs ys zs y z.
    ( Monad m
-   , Liftable xs zs
-   , Liftable ys zs
+   , LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    ) => Flow m ((y -> z) ': xs) -> Flow m (y ': ys) -> Flow m (z ': zs)
 {-# INLINABLE (<|<) #-}
@@ -640,8 +640,8 @@
 -- | Extract the first value, lift the result
 (.~~^^>) :: forall m a xs ys zs.
    ( Monad m
-   , Liftable xs zs
-   , Liftable ys zs
+   , LiftVariant xs zs
+   , LiftVariant ys zs
    ) => V (a ': ys) -> Flow m xs -> Flow m zs
 {-# INLINABLE (.~~^^>) #-}
 (.~~^^>) v f = v .~^^> const f
@@ -652,8 +652,8 @@
 -- | Extract the first value, lift the result
 (>.~~^^>) :: forall m a xs ys zs.
    ( Monad m
-   , Liftable xs zs
-   , Liftable ys zs
+   , LiftVariant xs zs
+   , LiftVariant ys zs
    ) => Flow m (a ': ys) -> Flow m xs -> Flow m zs
 {-# INLINABLE (>.~~^^>) #-}
 (>.~~^^>) = liftm (.~~^^>)
@@ -663,7 +663,7 @@
 -- | Extract the first value, connect to the expected output
 (.~~^>) :: forall m a ys zs.
    ( Monad m
-   , Liftable ys zs
+   , LiftVariant ys zs
    ) => V (a ': ys) -> Flow m zs -> Flow m zs
 {-# INLINABLE (.~~^>) #-}
 (.~~^>) v f = v .~^> const f
@@ -673,7 +673,7 @@
 -- | Extract the first value, connect to the expected output
 (>.~~^>) :: forall m a ys zs.
    ( Monad m
-   , Liftable ys zs
+   , LiftVariant ys zs
    ) => Flow m (a ': ys) -> Flow m zs -> Flow m zs
 {-# INLINABLE (>.~~^>) #-}
 (>.~~^>) = liftm (.~~^>)
@@ -700,8 +700,8 @@
 
 -- | Take the first output, fusion the result
 (.~~|>) ::
-   ( Liftable xs zs
-   , Liftable ys zs
+   ( LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    , Monad m
    ) => V (a ': ys) -> Flow m xs -> Flow m zs
@@ -712,8 +712,8 @@
 
 -- | Take the first output, fusion the result
 (>.~~|>) ::
-   ( Liftable xs zs
-   , Liftable ys zs
+   ( LiftVariant xs zs
+   , LiftVariant ys zs
    , zs ~ Union xs ys
    , Monad m
    ) => Flow m (a ': ys) -> Flow m xs -> Flow m zs
@@ -844,7 +844,7 @@
 -- | Extract the tail, lift the result
 (..~^^>) ::
    ( Monad m
-   , Liftable xs (a ': zs)
+   , LiftVariant xs (a ': zs)
    ) => V (a ': l) -> (V l -> Flow m xs) -> Flow m (a ': zs)
 {-# INLINABLE (..~^^>) #-}
 (..~^^>) v f = case popVariantHead v of
@@ -856,7 +856,7 @@
 -- | Extract the tail, lift the result
 (>..~^^>) ::
    ( Monad m
-   , Liftable xs (a ': zs)
+   , LiftVariant xs (a ': zs)
    ) => Flow m  (a ': l) -> (V l -> Flow m xs) -> Flow m (a ': zs)
 {-# INLINABLE (>..~^^>) #-}
 (>..~^^>) = liftm (..~^^>)
@@ -889,7 +889,7 @@
 (..?~^>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) ys
+   , LiftVariant (Remove a xs) ys
    ) => V (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': ys)
 {-# INLINABLE (..?~^>) #-}
 (..?~^>) v f = v ..~..> (\v' -> v' ?~^> f)
@@ -900,7 +900,7 @@
 (>..?~^>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) ys
+   , LiftVariant (Remove a xs) ys
    ) => Flow m (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': ys)
 {-# INLINABLE (>..?~^>) #-}
 (>..?~^>) = liftm (..?~^>)
@@ -911,7 +911,7 @@
 (..%~^>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) ys
+   , LiftVariant (Remove a xs) ys
    ) => V (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': ys)
 {-# INLINABLE (..%~^>) #-}
 (..%~^>) v f = v ..~..> (\v' -> v' %~^> f)
@@ -922,7 +922,7 @@
 (>..%~^>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) ys
+   , LiftVariant (Remove a xs) ys
    ) => Flow m (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': ys)
 {-# INLINABLE (>..%~^>) #-}
 (>..%~^>) = liftm (..%~^>)
@@ -933,8 +933,8 @@
 (..?~^^>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove a xs) zs
+   , LiftVariant ys zs
    ) => V (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': zs)
 {-# INLINABLE (..?~^^>) #-}
 (..?~^^>) v f = v ..~..> (\v' -> v' ?~^^> f)
@@ -945,8 +945,8 @@
 (>..?~^^>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove a xs) zs
+   , LiftVariant ys zs
    ) => Flow m (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': zs)
 {-# INLINABLE (>..?~^^>) #-}
 (>..?~^^>) = liftm (..?~^^>)
@@ -957,8 +957,8 @@
 (..%~^^>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove a xs) zs
+   , LiftVariant ys zs
    ) => V (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': zs)
 {-# INLINABLE (..%~^^>) #-}
 (..%~^^>) v f = v ..~..> (\v' -> v' %~^^> f)
@@ -969,8 +969,8 @@
 (>..%~^^>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove a xs) zs
+   , LiftVariant ys zs
    ) => Flow m (x ': xs) -> (a -> Flow m ys) -> Flow m (x ': zs)
 {-# INLINABLE (>..%~^^>) #-}
 (>..%~^^>) = liftm (..%~^^>)
@@ -981,7 +981,7 @@
 (..?~$>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) (x ': xs)
+   , LiftVariant (Remove a xs) (x ': xs)
    ) => V (x ': xs) -> (a -> Flow m (x ': xs)) -> Flow m (x ': xs)
 {-# INLINABLE (..?~$>) #-}
 (..?~$>) v f = case popVariantHead v of
@@ -994,7 +994,7 @@
 (>..?~$>) ::
    ( Monad m
    , a :<? xs
-   , Liftable (Filter a xs) (x ': xs)
+   , LiftVariant (Remove a xs) (x ': xs)
    ) => Flow m (x ': xs) -> (a -> Flow m (x ': xs)) -> Flow m (x ': xs)
 {-# INLINABLE (>..?~$>) #-}
 (>..?~$>) = liftm (..?~$>)
@@ -1005,7 +1005,7 @@
 (..%~$>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) (x ': xs)
+   , LiftVariant (Remove a xs) (x ': xs)
    ) => V (x ': xs) -> (a -> Flow m (x ': xs)) -> Flow m (x ': xs)
 {-# INLINABLE (..%~$>) #-}
 (..%~$>) v f = case popVariantHead v of
@@ -1018,7 +1018,7 @@
 (>..%~$>) ::
    ( Monad m
    , a :< xs
-   , Liftable (Filter a xs) (x ': xs)
+   , LiftVariant (Remove a xs) (x ': xs)
    ) => Flow m (x ': xs) -> (a -> Flow m (x ': xs)) -> Flow m (x ': xs)
 {-# INLINABLE (>..%~$>) #-}
 (>..%~$>) = liftm (..%~$>)
@@ -1090,7 +1090,7 @@
 (..?~!!>) ::
    ( Monad m
    , y :<? xs
-   ) => V (x ': xs) -> (y -> m ()) -> Flow m (x ': Filter y xs)
+   ) => V (x ': xs) -> (y -> m ()) -> Flow m (x ': Remove y xs)
 {-# INLINABLE (..?~!!>) #-}
 (..?~!!>) v f = v ..~..> (\xs -> xs ?~!!> f)
 
@@ -1100,7 +1100,7 @@
 (>..?~!!>) ::
    ( Monad m
    , y :<? xs
-   ) => Flow m (x ': xs) -> (y -> m ()) -> Flow m (x ': Filter y xs)
+   ) => Flow m (x ': xs) -> (y -> m ()) -> Flow m (x ': Remove y xs)
 {-# INLINABLE (>..?~!!>) #-}
 (>..?~!!>) = liftm (..?~!!>)
 
@@ -1110,7 +1110,7 @@
 (..%~!!>) ::
    ( Monad m
    , y :< xs
-   ) => V (x ': xs) -> (y -> m ()) -> Flow m (x ': Filter y xs)
+   ) => V (x ': xs) -> (y -> m ()) -> Flow m (x ': Remove y xs)
 {-# INLINABLE (..%~!!>) #-}
 (..%~!!>) v f = v ..~..> (\xs -> xs %~!!> f)
 
@@ -1120,7 +1120,7 @@
 (>..%~!!>) ::
    ( Monad m
    , y :< xs
-   ) => Flow m (x ': xs) -> (y -> m ()) -> Flow m (x ': Filter y xs)
+   ) => Flow m (x ': xs) -> (y -> m ()) -> Flow m (x ': Remove y xs)
 {-# INLINABLE (>..%~!!>) #-}
 (>..%~!!>) = liftm (..%~!!>)
 
@@ -1176,7 +1176,7 @@
 
 -- | Pop element, set the first value
 (?~.>) :: forall x xs y ys m.
-   ( ys ~ Filter x xs
+   ( ys ~ Remove x xs
    , Monad m
    , x :<? xs
    ) => V xs -> (x -> m y) -> Flow m (y ': ys)
@@ -1189,7 +1189,7 @@
 
 -- | Pop element, set the first value
 (>?~.>) ::
-   ( ys ~ Filter x xs
+   ( ys ~ Remove x xs
    , Monad m
    , x :<? xs
    ) => Flow m xs -> (x -> m y) -> Flow m (y ': ys)
@@ -1200,7 +1200,7 @@
 
 -- | Pop element, set the first value
 (%~.>) :: forall x xs y ys m.
-   ( ys ~ Filter x xs
+   ( ys ~ Remove x xs
    , Monad m
    , x :< xs
    ) => V xs -> (x -> m y) -> Flow m (y ': ys)
@@ -1211,7 +1211,7 @@
 
 -- | Pop element, set the first value
 (>%~.>) ::
-   ( ys ~ Filter x xs
+   ( ys ~ Remove x xs
    , Monad m
    , x :< xs
    ) => Flow m xs -> (x -> m y) -> Flow m (y ': ys)
@@ -1225,10 +1225,10 @@
    ( Monad m
    , x :<? xs
    , KnownNat (Length ys)
-   ) => V xs -> (x -> Flow m ys) -> Flow m (Concat ys (Filter x xs))
+   ) => V xs -> (x -> Flow m ys) -> Flow m (Concat ys (Remove x xs))
 {-# INLINABLE (?~+>) #-}
 (?~+>) v f = case popVariantMaybe v of
-   Right x -> appendVariant  @(Filter x xs) <$> f x
+   Right x -> appendVariant  @(Remove x xs) <$> f x
    Left ys -> prependVariant @ys            <$> return ys
 
 infixl 0 ?~+>
@@ -1238,7 +1238,7 @@
    ( Monad m
    , x :< xs
    , KnownNat (Length ys)
-   ) => Flow m xs -> (x -> Flow m ys) -> Flow m (Concat ys (Filter x xs))
+   ) => Flow m xs -> (x -> Flow m ys) -> Flow m (Concat ys (Remove x xs))
 {-# INLINABLE (>?~+>) #-}
 (>?~+>) = liftm (?~+>)
 
@@ -1249,7 +1249,7 @@
    ( Monad m
    , x :< xs
    , KnownNat (Length ys)
-   ) => V xs -> (x -> Flow m ys) -> Flow m (Concat ys (Filter x xs))
+   ) => V xs -> (x -> Flow m ys) -> Flow m (Concat ys (Remove x xs))
 {-# INLINABLE (%~+>) #-}
 (%~+>) = (?~+>)
 
@@ -1260,7 +1260,7 @@
    ( Monad m
    , x :< xs
    , KnownNat (Length ys)
-   ) => Flow m xs -> (x -> Flow m ys) -> Flow m (Concat ys (Filter x xs))
+   ) => Flow m xs -> (x -> Flow m ys) -> Flow m (Concat ys (Remove x xs))
 {-# INLINABLE (>%~+>) #-}
 (>%~+>) = liftm (%~+>)
 
@@ -1270,8 +1270,8 @@
 (?~^^>) :: forall x xs ys zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
    ) => V xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (?~^^>) #-}
 (?~^^>) v f = case popVariantMaybe v of
@@ -1284,8 +1284,8 @@
 (>?~^^>) :: forall x xs ys zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
    ) => Flow m xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (>?~^^>) #-}
 (>?~^^>) = liftm (?~^^>)
@@ -1296,8 +1296,8 @@
 (%~^^>) :: forall x xs ys zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
    ) => V xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (%~^^>) #-}
 (%~^^>) = (?~^^>)
@@ -1308,8 +1308,8 @@
 (>%~^^>) :: forall x xs ys zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
    ) => Flow m xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (>%~^^>) #-}
 (>%~^^>) = liftm (%~^^>)
@@ -1320,7 +1320,7 @@
 (?~^>) :: forall x xs zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
+   , LiftVariant (Remove x xs) zs
    ) => V xs -> (x -> Flow m zs) -> Flow m zs
 {-# INLINABLE (?~^>) #-}
 (?~^>) v f = case popVariantMaybe v of
@@ -1333,7 +1333,7 @@
 (>?~^>) :: forall x xs zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
+   , LiftVariant (Remove x xs) zs
    ) => Flow m xs -> (x -> Flow m zs) -> Flow m zs
 {-# INLINABLE (>?~^>) #-}
 (>?~^>) = liftm (?~^>)
@@ -1344,7 +1344,7 @@
 (%~^>) :: forall x xs zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
+   , LiftVariant (Remove x xs) zs
    ) => V xs -> (x -> Flow m zs) -> Flow m zs
 {-# INLINABLE (%~^>) #-}
 (%~^>) = (?~^>)
@@ -1355,7 +1355,7 @@
 (>%~^>) :: forall x xs zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
+   , LiftVariant (Remove x xs) zs
    ) => Flow m xs -> (x -> Flow m zs) -> Flow m zs
 {-# INLINABLE (>%~^>) #-}
 (>%~^>) = liftm (%~^>)
@@ -1408,9 +1408,9 @@
 (?~|>) :: forall x xs ys zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
-   , zs ~ Union (Filter x xs) ys
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
+   , zs ~ Union (Remove x xs) ys
    ) => V xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (?~|>) #-}
 (?~|>) v f = case popVariantMaybe v of
@@ -1423,9 +1423,9 @@
 (>?~|>) :: forall x xs ys zs m.
    ( Monad m
    , x :<? xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
-   , zs ~ Union (Filter x xs) ys
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
+   , zs ~ Union (Remove x xs) ys
    ) => Flow m xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (>?~|>) #-}
 (>?~|>) = liftm (?~|>)
@@ -1436,9 +1436,9 @@
 (%~|>) :: forall x xs ys zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
-   , zs ~ Union (Filter x xs) ys
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
+   , zs ~ Union (Remove x xs) ys
    ) => V xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (%~|>) #-}
 (%~|>) = (?~|>)
@@ -1449,9 +1449,9 @@
 (>%~|>) :: forall x xs ys zs m.
    ( Monad m
    , x :< xs
-   , Liftable (Filter x xs) zs
-   , Liftable ys zs
-   , zs ~ Union (Filter x xs) ys
+   , LiftVariant (Remove x xs) zs
+   , LiftVariant ys zs
+   , zs ~ Union (Remove x xs) ys
    ) => Flow m xs -> (x -> Flow m ys) -> Flow m zs
 {-# INLINABLE (>%~|>) #-}
 (>%~|>) = liftm (%~|>)
@@ -1546,7 +1546,7 @@
 (?~!!>) :: forall x xs m.
    ( Monad m
    , x :<? xs
-   ) => V xs -> (x -> m ()) -> Flow m (Filter x xs)
+   ) => V xs -> (x -> m ()) -> Flow m (Remove x xs)
 {-# INLINABLE (?~!!>) #-}
 (?~!!>) v f = case popVariantMaybe v of
    Right x -> f x >> error "?~!!> error"
@@ -1558,7 +1558,7 @@
 (>?~!!>) :: forall x xs m.
    ( Monad m
    , x :<? xs
-   ) => Flow m xs -> (x -> m ()) -> Flow m (Filter x xs)
+   ) => Flow m xs -> (x -> m ()) -> Flow m (Remove x xs)
 {-# INLINABLE (>?~!!>) #-}
 (>?~!!>) = liftm (?~!!>)
 
@@ -1568,7 +1568,7 @@
 (%~!!>) :: forall x xs m.
    ( Monad m
    , x :< xs
-   ) => V xs -> (x -> m ()) -> Flow m (Filter x xs)
+   ) => V xs -> (x -> m ()) -> Flow m (Remove x xs)
 {-# INLINABLE (%~!!>) #-}
 (%~!!>) = (?~!!>)
 
@@ -1578,7 +1578,7 @@
 (>%~!!>) :: forall x xs m.
    ( Monad m
    , x :< xs
-   ) => Flow m xs -> (x -> m ()) -> Flow m (Filter x xs)
+   ) => Flow m xs -> (x -> m ()) -> Flow m (Remove x xs)
 {-# INLINABLE (>%~!!>) #-}
 (>%~!!>) = liftm (%~!!>)
 
@@ -1624,7 +1624,7 @@
 -- | Select by type
 selectType ::
    ( x :< xs
-   ) => V xs -> Either (V (Filter x xs)) (V '[x])
+   ) => V xs -> Either (V (Remove x xs)) (V '[x])
 {-# INLINABLE selectType #-}
 selectType = fmap (toVariantAt @0) . popVariant
 
@@ -1686,8 +1686,8 @@
 
 -- | Union
 combineUnion ::
-   ( Liftable xs (Union xs ys)
-   , Liftable ys (Union xs ys)
+   ( LiftVariant xs (Union xs ys)
+   , LiftVariant ys (Union xs ys)
    ) => Either (V ys) (V xs) -> V (Union xs ys)
 {-# INLINABLE combineUnion #-}
 combineUnion = \case
@@ -1696,7 +1696,7 @@
 
 -- | Lift unselected
 combineLiftUnselected ::
-   ( Liftable ys xs
+   ( LiftVariant ys xs
    ) => Either (V ys) (V xs) -> V xs
 {-# INLINABLE combineLiftUnselected #-}
 combineLiftUnselected = \case
@@ -1705,8 +1705,8 @@
 
 -- | Lift both
 combineLiftBoth ::
-   ( Liftable ys zs
-   , Liftable xs zs
+   ( LiftVariant ys zs
+   , LiftVariant xs zs
    ) => Either (V ys) (V xs) -> V zs
 {-# INLINABLE combineLiftBoth #-}
 combineLiftBoth = \case
@@ -1907,7 +1907,7 @@
    , ContVariant xs
    , ys ~ FlattenVariant zs
    , Flattenable (V zs) (V ys)
-   , Liftable ys (Nub ys)
+   , LiftVariant ys (Nub ys)
    , rs ~ Nub ys
    ) => V xs -> fs -> V rs
 (~||) v fs = nubVariant (flattenVariant (v -|| fs))
@@ -1960,7 +1960,7 @@
    , ys ~ FlattenVariant ks
    , Flattenable (V ks) (V ys)
    , rs ~ Nub ys
-   , Liftable ys rs
+   , LiftVariant ys rs
    , Applicative m
    , JoinVariant m zs
    ) => V xs -> fs -> Flow m rs
@@ -1976,7 +1976,7 @@
    , ys ~ FlattenVariant ks
    , Flattenable (V ks) (V ys)
    , rs ~ Nub ys
-   , Liftable ys rs
+   , LiftVariant ys rs
    , Monad m
    , JoinVariant m zs
    ) => Flow m xs -> fs -> Flow m rs
diff --git a/src/lib/Haskus/Utils/VariantF.hs b/src/lib/Haskus/Utils/VariantF.hs
new file mode 100644
--- /dev/null
+++ b/src/lib/Haskus/Utils/VariantF.hs
@@ -0,0 +1,264 @@
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+-- | VariantF functor
+module Haskus.Utils.VariantF
+   ( VariantF (..)
+   , ApplyAll
+   , pattern FV
+   , appendVariantF
+   , toVariantFHead
+   , toVariantFTail
+   , popVariantFHead
+   , variantFToValue
+   , MapVariantF
+   , mapVariantF
+   , PopVariantF
+   , popVariantF
+   , LiftVariantF
+   , liftVariantF
+   , AlterVariantF
+   , alterVariantF
+   , AlgVariantF
+   , algVariantF
+   , SplitVariantF
+   , splitVariantF
+   , variantFToCont
+   , variantFToContM
+   , contToVariantF
+   , contToVariantFM
+   -- * Reexport
+   , NoConstraint
+   , module Haskus.Utils.Functor
+   )
+where
+
+import Haskus.Utils.Variant
+import Haskus.Utils.Functor
+import Haskus.Utils.Types.List
+import Haskus.Utils.ContFlow
+
+import Unsafe.Coerce
+import Data.Bifunctor
+import GHC.Exts (Any,Constraint)
+
+-- | Recursive Functor-like Variant
+newtype VariantF (xs :: [* -> *]) e
+   = VariantF (V (ApplyAll e xs))
+
+-- | Apply its first argument to every element of the 2nd arg list
+--
+-- > ApplyAll e '[f,g,h] ==> '[f e, g e, h e]
+--
+type family ApplyAll e (xs :: [* -> *]) :: [*] where
+   ApplyAll e '[]       = '[]
+   ApplyAll e (f ': fs) = f e ': ApplyAll e fs
+
+instance (Show (V (ApplyAll e xs))) => Show (VariantF xs e) where
+   show (VariantF x) = show x
+deriving instance (Eq (V (ApplyAll e xs))) => Eq (VariantF xs e)
+deriving instance (Ord (V (ApplyAll e xs))) => Ord (VariantF xs e)
+
+instance Functor (VariantF '[]) where
+   fmap _ = undefined
+
+instance (Functor (VariantF fs), Functor f) => Functor (VariantF (f ': fs)) where
+   fmap f (VariantF v) = case popVariantHead v of
+      Right x -> toVariantFHead (fmap f x)
+      Left xs -> toVariantFTail (fmap f (VariantF xs))
+
+-- | Pattern-match in a VariantF
+pattern FV :: forall c cs e. c :< (ApplyAll e cs) => c -> VariantF cs e
+pattern FV x = VariantF (V x)
+
+-- | Retrieve a single value
+variantFToValue :: VariantF '[f] e -> f e
+variantFToValue (VariantF v) = variantToValue v
+
+appendVariantF :: forall (ys :: [* -> *]) (xs :: [* -> *]) e.
+   ( ApplyAll e (Concat xs ys) ~ Concat (ApplyAll e xs) (ApplyAll e ys)
+   ) => VariantF xs e -> VariantF (Concat xs ys) e
+appendVariantF (VariantF v) = VariantF (appendVariant @(ApplyAll e ys) v)
+
+-- | Set the first value
+toVariantFHead :: forall x xs e. x e -> VariantF (x ': xs) e
+{-# INLINE toVariantFHead #-}
+toVariantFHead v = VariantF (toVariantHead @(x e) @(ApplyAll e xs) v)
+
+-- | Set the tail
+toVariantFTail :: forall x xs e. VariantF xs e -> VariantF (x ': xs) e
+{-# INLINE toVariantFTail #-}
+toVariantFTail (VariantF v) = VariantF (toVariantTail @(x e) @(ApplyAll e xs) v)
+
+-- | Pop VariantF head
+popVariantFHead :: forall x xs e. VariantF (x ': xs) e -> Either (VariantF xs e) (x e)
+{-# INLINE popVariantFHead #-}
+popVariantFHead (VariantF v) = case popVariantHead v of
+   Right x -> Right x
+   Left xs -> Left (VariantF xs)
+
+type PopVariantF x xs e =
+   ( x e :< ApplyAll e xs
+   , Remove (x e) (ApplyAll e xs) ~ ApplyAll e (Remove x xs)
+   )
+
+-- | Pop VariantF
+popVariantF :: forall x xs e.
+   ( PopVariantF x xs e
+   ) => VariantF xs e -> Either (VariantF (Remove x xs) e) (x e)
+{-# INLINE popVariantF #-}
+popVariantF (VariantF v) = case popVariant v of
+   Right x -> Right x
+   Left xs -> Left (VariantF xs)
+
+type MapVariantF a b cs ds e =
+   ( MapVariant (a e) (b e) (ApplyAll e cs)
+   , ds ~ ReplaceNS (IndexesOf a cs) b cs
+   , ApplyAll e ds ~ ReplaceNS (IndexesOf (a e) (ApplyAll e cs)) (b e) (ApplyAll e cs)
+   )
+
+-- | Map the matching types of a variant
+mapVariantF :: forall a b cs ds e.
+   ( MapVariantF a b cs ds e
+   ) => (a e -> b e) -> VariantF cs e -> VariantF ds e
+mapVariantF f (VariantF v) = VariantF (mapVariant @(a e) @(b e) @(ApplyAll e cs) f v)
+
+-- | xs is liftable in ys
+type LiftVariantF e xs ys =
+   ( IsSubset xs ys ~ 'True
+   , LiftVariant (ApplyAll e xs) (ApplyAll e ys)
+   )
+
+-- | Lift a VariantF into another
+liftVariantF :: forall e as bs.
+   ( LiftVariantF e as bs
+   ) => VariantF as e -> VariantF bs e
+liftVariantF (VariantF v) = VariantF (liftVariant' v)
+
+class AlterVariantF (c :: (* -> *) -> Constraint) e (xs :: [* -> *]) where
+   alterVariantF' :: (forall (f :: * -> *). c f => f e -> f e) -> Word -> Any -> Any
+
+instance AlterVariantF c e '[] where
+   {-# INLINE alterVariantF' #-}
+   alterVariantF' _ = undefined
+
+instance
+   ( AlterVariantF c e xs
+   , c x
+   ) => AlterVariantF c e (x ': xs)
+   where
+      {-# INLINE alterVariantF' #-}
+      alterVariantF' f t v =
+         case t of
+            0 -> unsafeCoerce (f (unsafeCoerce v :: x e))
+            n -> alterVariantF' @c @e @xs f (n-1) v
+
+-- | Alter a variant. You need to specify the constraints required by the
+-- modifying function.
+--
+-- Usage:
+--
+-- >   alterVariantF @NoConstraint id         v
+-- >   alterVariantF @Resizable    (resize 4) v
+-- >
+-- >   -- Multiple constraints:
+-- >   class (Ord a, Num a) => OrdNum a
+-- >   instance (Ord a, Num a) => OrdNum a
+-- >   alterVariantF @OrdNum foo v
+--
+alterVariantF :: forall c e (xs :: [* -> *]).
+   ( AlterVariantF c e xs
+   ) => (forall (f :: * -> *). c f => f e -> f e) -> VariantF xs e -> VariantF xs e
+{-# INLINABLE alterVariantF #-}
+alterVariantF f (VariantF (Variant t a)) =
+   VariantF (Variant t (alterVariantF' @c @e @xs f t a))
+
+
+class AlgVariantF (c :: (* -> *) -> Constraint) e (xs :: [* -> *]) where
+   algVariantF' :: (forall (f :: * -> *). c f => f e -> e) -> Word -> Any -> e
+
+instance AlgVariantF c e '[] where
+   {-# INLINE algVariantF' #-}
+   algVariantF' _ = undefined
+
+instance
+   ( AlgVariantF c e xs
+   , c x
+   ) => AlgVariantF c e (x ': xs)
+   where
+      {-# INLINE algVariantF' #-}
+      algVariantF' f t v =
+         case t of
+            0 -> f (unsafeCoerce v :: x e)
+            n -> algVariantF' @c @e @xs f (n-1) v
+
+-- | Apply an algebra to a VariantF. You need to specify the constraints
+-- required by the modifying function.
+--
+-- Usage:
+--
+-- >  algVariantF @NoConstraint id         v
+-- >  algVariantF @Resizable    (resize 4) v
+--
+algVariantF :: forall c e (xs :: [* -> *]).
+   ( AlgVariantF c e xs
+   ) => (forall (f :: * -> *). c f => f e -> e) -> VariantF xs e -> e
+{-# INLINABLE algVariantF #-}
+algVariantF f (VariantF (Variant t a)) = algVariantF' @c @e @xs f t a
+
+type SplitVariantF as xs e =
+   ( Complement (ApplyAll e xs) (ApplyAll e as) ~ ApplyAll e (Complement xs as)
+   , SplitVariant (ApplyAll e as) (ApplyAll e xs) (ApplyAll e xs)
+   )
+
+-- | Split a VariantF in two
+splitVariantF :: forall as xs e.
+   ( SplitVariantF as xs e
+   ) => VariantF xs e
+     -> Either (VariantF as e) (VariantF (Complement xs as) e)
+splitVariantF (VariantF v) = bimap VariantF VariantF (splitVariant v)
+
+-- | Convert a VariantF into a multi-continuation
+variantFToCont :: ContVariant (ApplyAll e xs)
+   => VariantF xs e -> ContFlow (ApplyAll e xs) r
+variantFToCont (VariantF v) = variantToCont v
+
+-- | Convert a VariantF into a multi-continuation
+variantFToContM ::
+   ( ContVariant (ApplyAll e xs)
+   , Monad m
+   ) => m (VariantF xs e) -> ContFlow (ApplyAll e xs) (m r)
+variantFToContM f = variantToContM (unvariantF <$> f)
+   where
+      unvariantF (VariantF v) = v
+
+-- | Convert a multi-continuation into a VariantF
+contToVariantF :: forall xs e.
+   ( ContVariant (ApplyAll e xs)
+   ) => ContFlow (ApplyAll e xs) (V (ApplyAll e xs)) -> VariantF xs e
+contToVariantF c = VariantF (contToVariant c)
+
+-- | Convert a multi-continuation into a VariantF
+contToVariantFM :: forall xs e m.
+   ( ContVariant (ApplyAll e xs)
+   , Monad m
+   ) => ContFlow (ApplyAll e xs) (m (V (ApplyAll e xs))) -> m (VariantF xs e)
+contToVariantFM f = VariantF <$> contToVariantM f
+
+instance ContVariant (ApplyAll e xs) => MultiCont (VariantF xs e) where
+   type MultiContTypes (VariantF xs e) = ApplyAll e xs
+   toCont = variantFToCont
+   toContM = variantFToContM
