packages feed

n-ary-functor 0.1.0.0 → 1.0

raw patch · 6 files changed

+793/−190 lines, 6 filesdep +n-ary-functordep +natural-transformationdep +transformersdep −doctest-discoverdep ~basebuild-type:Customsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: n-ary-functor, natural-transformation, transformers

Dependencies removed: doctest-discover

Dependency ranges changed: base

API changes (from Hackage documentation)

- NAryFunctor: NMap1 :: (forall a b. (a -> b) -> NMap k (f a) (f' b)) -> NMap1 k
- NAryFunctor: instance NAryFunctor.NFunctor (Data.Either.Either a)
- NAryFunctor: newtype NMap1 k (f :: Type -> k) (f' :: Type -> k)
+ NAryFunctor: (-#-) :: VarianceTransformer t a => t inner f g -> () -> inner (f a) (g a)
+ NAryFunctor: Contravariant1T :: (forall m m'. (Functor m, Functor m') => m' :~> m -> f m `to` f' m') -> Contravariant1T to f f'
+ NAryFunctor: ContravariantT :: (forall a a'. (a' -> a) -> f a `to` f' a') -> ContravariantT to f f'
+ NAryFunctor: Covariant1T :: (forall m m'. (Functor m, Functor m') => m :~> m' -> f m `to` f' m') -> Covariant1T to f f'
+ NAryFunctor: CovariantT :: (forall a a'. (a -> a') -> f a `to` f' a') -> CovariantT to f f'
+ NAryFunctor: Invariant1T :: (forall m m'. (Functor m, Functor m') => (m :~> m', m' :~> m) -> f m `to` f' m') -> Invariant1T to f f'
+ NAryFunctor: InvariantT :: (forall a a'. (a -> a', a' -> a) -> f a `to` f' a') -> InvariantT to f f'
+ NAryFunctor: NonvariantT :: (forall a a'. (a ~ a') => f a `to` f' a') -> NonvariantT to f f'
+ NAryFunctor: PhantomvariantT :: (forall a a'. () -> f a `to` f' a') -> PhantomvariantT to f f'
+ NAryFunctor: [<##>/>##<] :: Invariant1T to f f' -> forall m m'. (Functor m, Functor m') => (m :~> m', m' :~> m) -> f m `to` f' m'
+ NAryFunctor: [<##>] :: Covariant1T to f f' -> forall m m'. (Functor m, Functor m') => m :~> m' -> f m `to` f' m'
+ NAryFunctor: [<#>/>#<] :: InvariantT to f f' -> forall a a'. (a -> a', a' -> a) -> f a `to` f' a'
+ NAryFunctor: [>##<] :: Contravariant1T to f f' -> forall m m'. (Functor m, Functor m') => m' :~> m -> f m `to` f' m'
+ NAryFunctor: [>#<] :: ContravariantT to f f' -> forall a a'. (a' -> a) -> f a `to` f' a'
+ NAryFunctor: [unNonvariant] :: NonvariantT to f f' -> forall a a'. (a ~ a') => f a `to` f' a'
+ NAryFunctor: [👻#👻] :: PhantomvariantT to f f' -> forall a a'. () -> f a `to` f' a'
+ NAryFunctor: class VarianceTransformer (t :: (k -> k -> *) -> (k1 -> k) -> (k1 -> k) -> *) (a :: k1)
+ NAryFunctor: instance GHC.Base.Functor m => NAryFunctor.VarianceTransformer NAryFunctor.Contravariant1T m
+ NAryFunctor: instance GHC.Base.Functor m => NAryFunctor.VarianceTransformer NAryFunctor.Covariant1T m
+ NAryFunctor: instance GHC.Base.Functor m => NAryFunctor.VarianceTransformer NAryFunctor.Invariant1T m
+ NAryFunctor: instance NAryFunctor.NFunctor (->)
+ NAryFunctor: instance NAryFunctor.NFunctor Control.Monad.Trans.Reader.ReaderT
+ NAryFunctor: instance NAryFunctor.NFunctor Control.Monad.Trans.State.Lazy.StateT
+ NAryFunctor: instance NAryFunctor.NFunctor Control.Monad.Trans.Writer.Lazy.WriterT
+ NAryFunctor: instance NAryFunctor.NFunctor Data.Functor.Const.Const
+ NAryFunctor: instance NAryFunctor.VarianceTransformer NAryFunctor.ContravariantT a
+ NAryFunctor: instance NAryFunctor.VarianceTransformer NAryFunctor.CovariantT a
+ NAryFunctor: instance NAryFunctor.VarianceTransformer NAryFunctor.InvariantT a
+ NAryFunctor: instance forall k k1 (a :: k1). NAryFunctor.VarianceTransformer NAryFunctor.NonvariantT a
+ NAryFunctor: instance forall k k1 (a :: k1). NAryFunctor.VarianceTransformer NAryFunctor.PhantomvariantT a
+ NAryFunctor: instance forall k k1 (f :: k1 -> k) (t :: (k -> k -> GHC.Types.*) -> (k1 -> k) -> (k1 -> k) -> GHC.Types.*) (inner :: k -> k -> GHC.Types.*) (a :: k1). (NAryFunctor.NFunctor f, NAryFunctor.VarianceStack f ~ t inner, NAryFunctor.VarianceTransformer t a) => NAryFunctor.NFunctor (f a)
+ NAryFunctor: newtype Contravariant1T to f f'
+ NAryFunctor: newtype ContravariantT to f f'
+ NAryFunctor: newtype Covariant1T to f f'
+ NAryFunctor: newtype CovariantT to f f'
+ NAryFunctor: newtype Invariant1T to f f'
+ NAryFunctor: newtype InvariantT to f f'
+ NAryFunctor: newtype NonvariantT to f f'
+ NAryFunctor: newtype PhantomvariantT to f f'
+ NAryFunctor: type family VarianceStack f :: k -> k -> *;
+ NAryFunctor: }
- NAryFunctor: [<#>] :: NMap1 k -> forall a b. (a -> b) -> NMap k (f a) (f' b)
+ NAryFunctor: [<#>] :: CovariantT to f f' -> forall a a'. (a -> a') -> f a `to` f' a'
- NAryFunctor: class NFunctor (f :: k)
+ NAryFunctor: class NFunctor (f :: k) where type VarianceStack f :: k -> k -> * where {
- NAryFunctor: nmap :: NFunctor f => NMap k f f
+ NAryFunctor: nmap :: NFunctor f => VarianceStack f f f

Files

CHANGELOG.md view
@@ -1,3 +1,32 @@+## New in 1.0++* Breaking change: all instances now need to specify the variance of all type+  parameters.+* Breaking change: instances of the form `NFunctor (f a)` are no longer+  allowed. Instead, write `NFunctor f` and use `NonvariantT` to indicate that+  `a` cannot be mapped.+* `NFunctor` is now even more general: in addition to generalizing `Functor`,+  `Bifunctor`, `Trifunctor`, etc., it now also generalizes `Contravariant`,+  `Invariant`, and `Profunctor`!+* Introducing new infix operators corresponding to each variance. `(<#>)` is+  still used for covariant type parameters, so after updating the instances,+  all the call sites which were using the 0.1 API should still work. `(>#<)` is+  used for contravariant type parameters, `(<#>/>#<)` is used for invariant+  type parameters, which can be mapped given both a covariant and a+  contravariant function, and `(👻#👻)` is used for phantom type parameters.+* Introducing the `(-#-)` operator, which can be used instead of any other+  operator in order to leave the corresponding type parameter untouched.+* Introducing support for mapping over type parameters of kind `* -> *` using+  natural transformations. The corresponding infix operators have two hashes:+  the covariant operator is `(<##>)`, the contravariant operator is `(>##<)`,+  etc.+* Introducing the `VarianceTransformer` typeclass, via which you can add+  support for other variances and other kinds.+* It is no longer needed (nor allowed) to write both an `NFunctor Either`+  instance and an `NFunctor (Either a)` instance corresponding to `Either`'s+  `Bifunctor` and `Functor` instances. Instead, the `NFunctor (Either a)`+  instance is derived from the `NFunctor Either` instance.+ ## New in 0.1.0.0  * Initial release of the `NFunctor` typeclass
README.md view
@@ -1,14 +1,160 @@-# N-ary Functors+# N-ary Functors [![Hackage](https://img.shields.io/hackage/v/n-ary-functor.svg)](https://hackage.haskell.org/package/n-ary-functor) [![Build Status](https://secure.travis-ci.org/gelisam/n-ary-functor.png?branch=master)](https://travis-ci.org/gelisam/n-ary-functor) +## Using existing instances+ [`Functor`](https://hackage.haskell.org/package/base-4.10.1.0/docs/Prelude.html#t:Functor) and [`Bifunctor`](https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Bifunctor.html#t:Bifunctor) are both in `base`, but what about `Trifunctor`? `Quadrifunctor`? There must be a better solution than creating an infinite tower of typeclasses. Here's the API I managed to implement: -    > nmap <#> (+1) <#> (+2) $ (0, 0)-    (1,2)+```haskell+> nmap <#> (+1) <#> (+2) $ (0, 0)+(1,2) -    > nmap <#> (+1) <#> (+2) <#> (+3) $ (0, 0, 0)-    (1,2,3)+> nmap <#> (+1) <#> (+2) <#> (+3) $ (0, 0, 0)+(1,2,3) -    > nmap <#> (+1) <#> (+2) <#> (+3) <#> (+4) $ (0, 0, 0, 0)-    (1,2,3,4)+> nmap <#> (+1) <#> (+2) <#> (+3) <#> (+4) $ (0, 0, 0, 0)+(1,2,3,4)+``` -For more details, see the [documentation](https://hackage.haskell.org/package/n-ary-functor-0.1.0.0/docs/NAryFunctor.html) and the [blog post](http://gelisam.blogspot.ca/2017/12/n-ary-functors.html).+What about [`Contravariant`](https://www.stackage.org/haddock/lts-14.20/base-4.12.0.0/Data-Functor-Contravariant.html#t:Contravariant) and [`Profunctor`](https://www.stackage.org/haddock/lts-14.20/profunctors-5.3/Data-Profunctor.html#t:Profunctor)? No need to define `Bicontravariant` nor `Noobfunctor`, the `NFunctor` typeclass supports contravariant type-parameters too!++```haskell+> let intToInt       =                            succ+> let intToString    = nmap            <#> show $ succ+> let stringToString = nmap >#< length <#> show $ succ+> intToInt 3+4+> intToString 3+"4"+> stringToString "foo"+"4"+```++As the examples above demonstrate, n-ary-functor has an equivalent for both the `Functor ((->) a)` instance and the `Profunctor (->)` instance. Even better: when writing your own instance, you only need to define an `NFunctor (->)` instance, and the `NFunctor ((->) a)` instance will be derived for you. `NFunctor ((->) a b)` too, but that's less useful since that `nmap` is just the identity function.++That's not all! Consider a type like `StateT s m a`. The last type parameter is covariant, but what about the first two? Well, `s -> m (a, s)` has both positive and negative occurences of `s`, so you need both an `s -> t` and a `t -> s` function in order to turn a `StateT s m a` into a `StateT t m a`. And what about `m`? You need a natural transformation `forall a. m a -> n a`. Yes, n-ary-functor supports these too!++```haskell+> let stateIntIdentityInt    = ((`div` 2) <$> get) >>= lift . Identity+> let stateStringMaybeString = nmap+                       <#>/>#< (flip replicate '.', length)  -- (s -> t, t -> s)+                          <##> NT (Just . runIdentity)       -- NT (forall a. m a -> n a)+                           <#> show                          -- a -> b+                             $ stateIntIdentityInt+> runStateT stateIntIdentityInt 4+Identity (2,4)+> runStateT stateStringMaybeString "four"+Just ("2","....")+```++Notice how even in such a complicated case, no type annotations are needed, as n-ary-functor is written with type inference in mind.+++## Defining your own instance++When defining an instance of `NFunctor`, you need to specify the variance of every type parameter using a "variance stack" ending with `(->)`. Here is the instance for `(,,)`, whose three type parameters are covariant:++```haskell+instance NFunctor (,,) where+  type VarianceStack (,,) = CovariantT (CovariantT (CovariantT (->)))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> \(x1,x2,x3)+      -> (f1 x1, f2 x2, f3 x3)+```++Its `nmap` then receives 3 functions, which it applies to the 3 components of the 3-tuple.++Here is a more complicated instance, that of `StateT`:++```haskell+instance NFunctor StateT where+  type VarianceStack StateT = InvariantT (Covariant1T (CovariantT (->)))+  nmap = InvariantT  $ \(f1, f1')+      -> Covariant1T $ \f2+      -> CovariantT  $ \f3+      -> \body+      -> StateT $ \s'+      -> fmap (f3 *** f1) $ unwrapNT f2 $ runStateT body $ f1' s'+```++The `s` type parameter is "invariant", a standard but confusing name which does _not_ mean that the parameter cannot vary, but rather that we need both an `s -> t` and a `t -> s`. The `m` parameter is covariant, but for a type parameter of kind `* -> *`, so we follow the [convention](http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Functor-Classes.html) and add a `1` to the name of the variance transformer, hence `Covariant1T`.+++## Defining your own variance transformer++We've seen plenty of strange variances already and n-ary-functor provides stranger ones still (can you guess what the `👻#👻` operator does?), but if your type parameters vary in an even more unusual way, you can define your own variance transformer. Here's what the definition of `CovariantT` looks like:++```haskell+newtype CovariantT to f g = CovariantT+  { (<#>) :: forall a b+           . (a -> b)+          -> f a `to` g b+  }+```++One thing which is unusual in that newtype definition is that instead of naming the eliminator `unCovariantT`, we give it the infix name `(<#>)`. See [this blog post](http://gelisam.blogspot.com/2017/12/n-ary-functors.html#ergonomics) for more details on that aspect.++Let's look at the type wrapped by the newtype. `to` is the rest of the variance stack, so in the simplest case, `to` is just `(->)`, in which case the wrapped type is `(a -> b) -> f a -> g b`, which is really close to the type of `fmap`. The reason we produce a `g b` instead of an `f b` is because previous type parameters might already be mapped; for example, in `nmap <#> show <#> show $ (0, 0)`, the overall transformation has type `(,) Int Int -> (,) String String`, so from the point of view of the second `(<#>)`, `f` is `(,) Int` and `g` is `(,) String`.++One last thing is that variance transformers must implement the `VarianceTransformer` typeclass. It simply ensures that there exists a neutral argument, in this case `id`, which doesn't change the type parameter at all.++```haskell+instance VarianceTransformer CovariantT a where+  t -#- () = t <#> id+```+++### Flavor example++A concrete situation in which you'd want to define your own variance transformer is if you have a DataKind type parameter which corresponds to a number of other types via type families.++```haskell+import qualified Data.ByteString      as Strict+import qualified Data.ByteString.Lazy as Lazy+import qualified Data.Text            as Strict+import qualified Data.Text.Lazy       as Lazy++data Flavor+  = Strict+  | Lazy++type family ByteString (flavor :: Flavor) :: * where+  ByteString 'Lazy   = Lazy.ByteString+  ByteString 'Strict = Strict.ByteString++type family Text (flavor :: Flavor) :: * where+  Text 'Lazy   = Lazy.Text+  Text 'Strict = Strict.Text++data File (flavor :: Flavor) = File+  { name     :: Text flavor+  , size     :: Int+  , contents :: ByteString flavor+  }+```++In order to convert a `File 'Lazy` to a `File 'Strict`, we need to map both the underlying `Text 'Lazy` to a `Text 'Strict` and the underlying `ByteString 'Lazy` to a `ByteString 'Strict`. So those are exactly the two functions our custom variance transformer will ask for:++```haskell+newtype FlavorvariantT to f g = FlavorvariantT+  { (😋#😋) :: forall flavor1 flavor2+           . ( ByteString flavor1 -> ByteString flavor2+             , Text       flavor1 -> Text       flavor2+             )+          -> f flavor1 `to` g flavor2+  }++instance VarianceTransformer FlavorvariantT a where+  t -#- () = t 😋#😋 (id, id)+```++We can now implement our `NFunctor File` instance by specifying that its `flavor` type parameter is flavorvariant.++```haskell+instance NFunctor File where+  type VarianceStack File = FlavorvariantT (->)+  nmap = FlavorvariantT $ \(f, g)+      -> \(File n s c)+      -> File (g n) s (f c)+```
Setup.hs view
@@ -1,2 +1,6 @@-import Distribution.Simple-main = defaultMain+module Main where++import Distribution.Extra.Doctest (defaultMainWithDoctests)++main :: IO ()+main = defaultMainWithDoctests "doctests"
n-ary-functor.cabal view
@@ -1,27 +1,47 @@ name:                n-ary-functor-version:             0.1.0.0+version:             1.0 synopsis:            An n-ary version of Functor-description:         A single typeclass for Functor, Bifunctor, Trifunctor, etc.+description:         A single typeclass for Functor, Bifunctor, Profunctor, etc. homepage:            https://github.com/gelisam/n-ary-functor license:             PublicDomain author:              Samuel Gélineau maintainer:          gelisam+github@gmail.com category:            Data-build-type:          Simple+build-type:          Custom cabal-version:       >=1.10 extra-source-files:  README.md                    , CHANGELOG.md +source-repository head+   type: git+   location: https://github.com/gelisam/n-ary-functor++source-repository this+   type: git+   location: https://github.com/gelisam/n-ary-functor+   tag: v1.0++custom-setup+ setup-depends:+   base >= 4 && <5,+   Cabal,+   cabal-doctest >= 1 && <1.1+ library+  ghc-options:         -Wall   exposed-modules:     NAryFunctor-  build-depends:       base >=4.9 && <4.11+  build-depends:       base >=4.9 && <5+                     , natural-transformation >= 0.4+                     , transformers -any   hs-source-dirs:      src   default-language:    Haskell2010  test-suite doctests   default-language:   Haskell2010   type:               exitcode-stdio-1.0-  ghc-options:        -threaded+  ghc-options:        -Wall -threaded   main-is:            doctests.hs-  build-depends:      base >4 && <5, doctest, doctest-discover-  HS-Source-Dirs:     test+  build-depends:      base >4 && <5+                    , doctest+                    , n-ary-functor+  hs-source-dirs:     test
src/NAryFunctor.hs view
@@ -1,90 +1,469 @@-{-# LANGUAGE RankNTypes, TypeFamilies, TypeFamilyDependencies, TypeInType #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, PolyKinds, RankNTypes, TypeFamilies, TypeOperators, UndecidableInstances, UnicodeSyntax #-} module NAryFunctor   ( NFunctor(..)--  -- * Internals-  , NMap1(..), NMap+  , VarianceTransformer(..)+  , CovariantT(..),     Covariant1T(..)+  , ContravariantT(..), Contravariant1T(..)+  , InvariantT(..),     Invariant1T(..)+  , NonvariantT(..)+  , PhantomvariantT(..)   ) where +import Control.Arrow+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State+import Control.Monad.Trans.Writer+import Control.Natural import Data.Bifunctor+import Data.Functor.Const import Data.Functor.Identity-import Data.Kind (Type) +-- $setup+-- >>> import Control.Monad.Trans.Class+-- >>> let (<&>) = flip (<$>) + -- |--- A generalization of 'Functor', 'Bifunctor', 'Trifunctor', etc.+-- A generalization of 'Functor', 'Bifunctor', 'Contravariant', 'Profunctor', etc. ----- Example usage:+-- * @(NFunctor f, VarianceStack f ~ CovariantT (->)@ is equivalent to @Functor f@.+-- * @(NFunctor f, VarianceStack f ~ CovariantT (CovariantT (->))@ is equivalent to+--   @Bifunctor f@.+-- * @(NFunctor f, VarianceStack f ~ ContravariantT (->)@ is equivalent to+--   @Contravariant f@.+-- * @(NFunctor f, VarianceStack f ~ InvariantT (->)@ is equivalent to+--   @Invariant f@.+-- * @(NFunctor f, VarianceStack f ~ ContravariantT (CovariantT (->))@ is equivalent+--   to @Profunctor f@. ----- >>> nmap <#> (+1) $ Identity (0::Int)--- Identity 1+-- The associated type 'VarianceStack' specifies the variance of all the type+-- parameters using a stack of 'VarianceTransformer's ending with @(->)@. ----- >>> nmap <#> (+1) <#> (+2) $ (0::Int, 0::Int)--- (1,2)+-- Example instance: ----- >>> nmap <#> (+1) <#> (+2) <#> (+3) $ (0::Int, 0::Int, 0::Int)--- (1,2,3)+-- > instance NFunctor (,,) where+-- >   type VarianceStack (,,) = CovariantT (CovariantT (CovariantT (->)))+-- >   nmap = CovariantT $ \f1+-- >       -> CovariantT $ \f2+-- >       -> CovariantT $ \f3+-- >       -> \(x1,x2,x3)+-- >       -> (f1 x1, f2 x2, f3 x3) --+-- Note that it is /not/ possible to write an instance for a partially-applied+-- type; for example, it is not possible to write an @NFunctor ((,,) a)@+-- instance corresponding to the @Functor ((,,) a)@ instance. Instead, the+-- @NFunctor ((,,) a)@ and @NFunctor ((,,) a b)@ instances are derived from the+-- above instance.+-- -- Laws: ----- > nmap <#> id <#> ... <#> id = id--- > (nmap <#> f1 <#> ... <#> fN) . (nmap <#> g1 <#> ... <#> gN) = nmap <#> (f1 . g1) <#> ... <#> (fN . gN)+-- > nmap <#>     id       = nmap -#- () = id+-- > nmap     >#< id       = nmap -#- () = id+-- > nmap <#>/>#< (id, id) = nmap -#- () = id+-- > ... ----- Example instance:+-- > nmap -#- () -#- () <#> f =+-- > nmap        -#- () <#> f =+-- > nmap               <#> f ----- > instance NFunctor (,,) where--- >   nmap = NMap1 $ \f1--- >       -> NMap1 $ \f2--- >       -> NMap1 $ \f3--- >       -> \(x1,x2,x3)--- >       -> (f1 x1, f2 x2, f3 x3)+-- > (nmap <#> f1 <#> f2) . (nmap <#> g1 <#> g2) = nmap <#> (f1 . g1) <#> (f2 . g2)+-- > (nmap >#< f1 >#< f2) . (nmap >#< g1 >#< g2) = nmap >#< (g1 . f1) >#< (g2 . f2)+-- > ... class NFunctor (f :: k) where-  nmap :: NMap k f f+  type VarianceStack f :: k -> k -> *+  nmap :: VarianceStack f f f   -- |--- Types like 'Either' which have both a 'Functor' and a 'Bifunctor' instance--- can have more than one 'NFunctor' instance. Those instances all define the--- same method, 'nmap', but they return a value of a different type, which is--- how the correct 'NFunctor' instance is picked:------ > nmap :: NMap1 Type (Either a) (Either a)    -- Functor--- > nmap :: NMap1 (Type -> Type) Either Either  -- Bifunctor+-- This library uses a stack of 'VarianceTransformer's to indicate the variance+-- of each type parameter. Each transformer in the stack specifies the variance+-- of one type parameter, and wraps an inner stack specifying the variance of+-- the remaining type parameters, until we reach @(->)@, the base of the stack. ----- This 'NMap1' is unwrapped by using '<#>' to pass in the next input function.--- In the case of @NMap1 (Type -> Type)@, the result after passing this input--- function is another 'NMap1', which needs to be unwrapped using a second--- '<#>'. The end result is that the 'Functor' behaviour is obtained by using a--- single '<#>', and the 'Bifunctor' behaviour is obtained by using two.+-- Each 'VarianceTransformer' is eliminated by an infix function, such as+-- @(\<\#\>)@. This function takes a stack on the left, and its second argument+-- has whatever type is necessary in order to map over the corresponding+-- type parameter; for covariant type parameters, it will be a function of type+-- @(a -> b)@, for contravariant type parameters, it will be a function of+-- type @(b -> a)@, for invariant type parameters, it will be a pair of+-- functions @(a -> b, b -> a)@, etc. ----- >>> nmap <#> (+1) $ Right (0::Int)--- Right 1--- >>> nmap <#> (+1) <#> (+2) $ Left (0::Int)--- Left 1-newtype NMap1 k (f :: Type -> k) (f' :: Type -> k) = NMap1-  { (<#>) :: forall a b. (a -> b) -> NMap k (f a) (f' b)+-- The @(-\#-)@ method witnesses the fact that regardless of the variance of a+-- given type parameter, there is always an identity-like argument which can be+-- passed as that second argument which will cause that type parameter to be+-- left unchanged. It takes a stack on the left, and its second argument is+-- simply @()@.+class VarianceTransformer (t :: (k -> k -> *)+                             -> (k1 -> k) -> (k1 -> k) -> *)+                          (a :: k1)+                          where+  (-#-) :: t inner f g -> () -> inner (f a) (g a)+++newtype CovariantT to f f' = CovariantT+  { (<#>) :: forall a a'+           . (a -> a')+          -> f a `to` f' a'   } -type family NMap k = (r :: k -> k -> Type) | r -> k where-  NMap Type        = (->)-  NMap (Type -> k) = NMap1 k+instance VarianceTransformer CovariantT a where+  t -#- () = t <#> id  --- | For kind @* -> *@ ('Functor'), 'nmap' must be @NMap1 fmap@.------ >>> nmap <#> (+1) $ Right (0::Int)--- Right 1-instance NFunctor (Either a) where-  nmap = NMap1 fmap+newtype ContravariantT to f f' = ContravariantT+  { (>#<) :: forall a a'+           . (a' -> a)+          -> f a `to` f' a'+  } --- | For kind @* -> * -> *@ ('Bifunctor'), 'nmap' must be @NMap1 $ \f1 -> NMap1 $ \f2 -> bimap f1 f2@.+instance VarianceTransformer ContravariantT a where+  t -#- () = t >#< id+++newtype InvariantT to f f' = InvariantT+  { (<#>/>#<) :: forall a a'+               . (a -> a', a' -> a)+              -> f a `to` f' a'+  }++instance VarianceTransformer InvariantT a where+  t -#- () = t <#>/>#< (id, id)+++-- |+-- If you can't figure out how to map over a particular type parameter, use+-- this variance and we'll leave it alone. The corresponding infix operator is+-- @(-\#-)@.+newtype NonvariantT to f f' = NonvariantT+  { unNonvariant :: forall a a'. (a ~ a')+                 => f a `to` f' a'+  }++instance VarianceTransformer NonvariantT a where+  t -#- () = unNonvariant t+++-- |+-- Phantom type parameters can be changed to any other type, no @a -> b@+-- function needed, so we only ask for a @()@. Use @(-\#-)@ in the common case+-- in which you don't want to change the phantom type, and @(👻#👻)@ in the+-- rare case in which you do want to change it.+newtype PhantomvariantT to f f' = PhantomvariantT+  { (👻#👻) :: forall a a'+             . ()+            -> f a `to` f' a'+  }++instance VarianceTransformer PhantomvariantT a where+  t -#- () = t 👻#👻 ()++++newtype Covariant1T to f f' = Covariant1T+  { (<##>) :: forall m m'. (Functor m, Functor m')+           => m :~> m'+           -> f m `to` f' m'+  }++instance Functor m+      => VarianceTransformer Covariant1T m where+  t -#- () = t <##> NT id+++newtype Contravariant1T to f f' = Contravariant1T+  { (>##<) :: forall m m'. (Functor m, Functor m')+           => m' :~> m+           -> f m `to` f' m'+  }++instance Functor m+      => VarianceTransformer Contravariant1T m where+  t -#- () = t >##< NT id+++newtype Invariant1T to f f' = Invariant1T+  { (<##>/>##<) :: forall m m'. (Functor m, Functor m')+                => (m :~> m', m' :~> m)+                -> f m `to` f' m'+  }++instance Functor m+      => VarianceTransformer Invariant1T m where+  t -#- () = t <##>/>##< (NT id, NT id)++++-- |+-- A bold instance! We should be suspicious of any instance for @f a@, because+-- it is likely to overlap with other instances. For instance, what if we want+-- to define an @NFunctor ((->) a)@ instance corresponding to the @Functor ((->) a)@+-- instance? --+-- I claim that you will never have to write such an instance; it will always+-- be possible to write the @NFunctor (->)@ instance instead, and to have the+-- @NFunctor ((->) a)@ derived from the @NFunctor (->)@ instance via this bold+-- instance. If you really can't find a way to map over a type parameter, use+-- 'NonvariantT' to skip over it.+instance ( NFunctor f+         , VarianceStack f ~ t inner+         , VarianceTransformer t a+         )+      => NFunctor (f a) where+  --type VarianceStack (f a) = inner+  type VarianceStack (f a) = VarianceStack'Tail (VarianceStack f)+  nmap = nmap -#- ()++-- We can't write @type VarianceStack (f a) = inner@, ghc complains that 'inner' is not+-- in scope, so we instead have to write this type family which extracts 'inner'+-- from @VarianceStack f@.+type family VarianceStack'Tail f where+  VarianceStack'Tail (t inner) = inner++++-- Instances++-- $+-- >>> nmap          <#> (+2) $ Right (0::Int)+-- Right 2 -- >>> nmap <#> (+1) <#> (+2) $ Left (0::Int) -- Left 1+--+-- >>> nmap          -#- ()   $ Right (0::Int)+-- Right 0+-- >>> nmap <#> (+1) -#- ()   $ Left (0::Int)+-- Left 1+-- >>> nmap -#- ()   <#> (+2) $ Right (0::Int)+-- Right 2+-- >>> nmap -#- ()   -#- ()   $ Left (0::Int)+-- Left 0 instance NFunctor Either where-  nmap = NMap1 $ \f1 -> NMap1 $ \f2 -> bimap f1 f2+  type VarianceStack Either = CovariantT (CovariantT (->))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> bimap f1 f2 +-- $+-- >>> let intToInt       =                            succ+-- >>> let intToString    = nmap            <#> show $ succ+-- >>> let stringToString = nmap >#< length <#> show $ succ+-- >>> intToInt 3+-- 4+-- >>> intToString 3+-- "4"+-- >>> stringToString "foo"+-- "4"+--+-- >>> let intToInt    = nmap            -#- ()   $ succ+-- >>> let stringToInt = nmap >#< length -#- ()   $ succ+-- >>> let intToString = nmap -#- ()     <#> show $ succ+-- >>> let intToInt'   = nmap -#- ()     -#- ()   $ succ+-- >>> intToInt 3+-- 4+-- >>> stringToInt "foo"+-- 4+-- >>> intToString 3+-- "4"+-- >>> intToInt' 3+-- 4+instance NFunctor (->) where+  type VarianceStack (->) = ContravariantT (CovariantT (->))+  nmap = ContravariantT $ \f1'+      -> CovariantT $ \f2+      -> \g+      -> f2 . g . f1' +-- $+-- >>> let readerIntIdentityInt    = ((`div` 2) <$> ask) >>= lift . Identity+-- >>> let readerIntIdentityString = nmap                                         <#> show $ readerIntIdentityInt+-- >>> let readerIntMaybeString    = nmap            <##> NT (Just . runIdentity) <#> show $ readerIntIdentityInt+-- >>> let readerStringMaybeString = nmap >#< length <##> NT (Just . runIdentity) <#> show $ readerIntIdentityInt+-- >>> runReaderT readerIntIdentityInt 4+-- Identity 2+-- >>> runReaderT readerIntIdentityString 4+-- Identity "2"+-- >>> runReaderT readerIntMaybeString 4+-- Just "2"+-- >>> runReaderT readerStringMaybeString "four"+-- Just "2"+--+-- >>> let readerIntIdentityInt'      = nmap                                         -#- ()   $ readerIntIdentityInt+-- >>> let readerIntMaybeInt          = nmap            <##> NT (Just . runIdentity) -#- ()   $ readerIntIdentityInt+-- >>> let readerIntIdentityString    = nmap            -#-  ()                      <#> show $ readerIntIdentityInt+-- >>> let readerIntIdentityInt''     = nmap            -#-  ()                      -#- ()   $ readerIntIdentityInt+-- >>> let readerStringMaybeInt       = nmap >#< length <##> NT (Just . runIdentity) -#- ()   $ readerIntIdentityInt+-- >>> let readerStringIdentityString = nmap >#< length -#-  ()                      <#> show $ readerIntIdentityInt+-- >>> let readerStringIdentityInt    = nmap >#< length -#-  ()                      -#- ()   $ readerIntIdentityInt+-- >>> let readerIntMaybeString       = nmap -#- ()     <##> NT (Just . runIdentity) <#> show $ readerIntIdentityInt+-- >>> let readerIntMaybeInt'         = nmap -#- ()     <##> NT (Just . runIdentity) -#- ()   $ readerIntIdentityInt+-- >>> let readerIntIdentityString'   = nmap -#- ()     -#-  ()                      <#> show $ readerIntIdentityInt+-- >>> let readerIntIdentityInt'''    = nmap -#- ()     -#-  ()                      -#- ()   $ readerIntIdentityInt+-- >>> runReaderT readerIntIdentityInt' 4+-- Identity 2+-- >>> runReaderT readerIntMaybeInt 4+-- Just 2+-- >>> runReaderT readerIntIdentityString 4+-- Identity "2"+-- >>> runReaderT readerIntIdentityInt'' 4+-- Identity 2+-- >>> runReaderT readerStringMaybeInt "four"+-- Just 2+-- >>> runReaderT readerStringIdentityString "four"+-- Identity "2"+-- >>> runReaderT readerStringIdentityInt "four"+-- Identity 2+-- >>> runReaderT readerIntMaybeString 4+-- Just "2"+-- >>> runReaderT readerIntMaybeInt' 4+-- Just 2+-- >>> runReaderT readerIntIdentityString' 4+-- Identity "2"+-- >>> runReaderT readerIntIdentityInt''' 4+-- Identity 2+instance NFunctor (ReaderT :: * -> (* -> *) -> * -> *) where+  type VarianceStack ReaderT = ContravariantT (Covariant1T (CovariantT (->)))+  nmap = ContravariantT $ \f1'+      -> Covariant1T $ \f2+      -> CovariantT $ \f3+      -> \body+      -> ReaderT $ \r'+      -> fmap f3 $ unwrapNT f2 $ runReaderT body $ f1' r'++-- $+-- >>> let stateIntIdentityInt    = ((`div` 2) <$> get) >>= lift . Identity+-- >>> let stateIntIdentityString = nmap                                                                   <#> show $ stateIntIdentityInt+-- >>> let stateIntMaybeString    = nmap                                      <##> NT (Just . runIdentity) <#> show $ stateIntIdentityInt+-- >>> let stateStringMaybeString = nmap <#>/>#< (flip replicate '.', length) <##> NT (Just . runIdentity) <#> show $ stateIntIdentityInt+-- >>> runStateT stateIntIdentityInt 4+-- Identity (2,4)+-- >>> runStateT stateIntIdentityString 4+-- Identity ("2",4)+-- >>> runStateT stateIntMaybeString 4+-- Just ("2",4)+-- >>> runStateT stateStringMaybeString "four"+-- Just ("2","....")+--+-- >>> let stateIntIdentityInt'      = nmap                                                                           -#- ()   $ stateIntIdentityInt+-- >>> let stateIntMaybeInt          = nmap                                              <##> NT (Just . runIdentity) -#- ()   $ stateIntIdentityInt+-- >>> let stateIntIdentityString    = nmap                                              -#-  ()                      <#> show $ stateIntIdentityInt+-- >>> let stateIntIdentityInt''     = nmap                                              -#-  ()                      -#- ()   $ stateIntIdentityInt+-- >>> let stateStringMaybeInt       = nmap <#>/>#< (flip replicate '.', length) <##> NT (Just . runIdentity) -#- ()   $ stateIntIdentityInt+-- >>> let stateStringIdentityString = nmap <#>/>#< (flip replicate '.', length) -#-  ()                      <#> show $ stateIntIdentityInt+-- >>> let stateStringIdentityInt    = nmap <#>/>#< (flip replicate '.', length) -#-  ()                      -#- ()   $ stateIntIdentityInt+-- >>> let stateIntMaybeString       = nmap -#-     ()                           <##> NT (Just . runIdentity) <#> show $ stateIntIdentityInt+-- >>> let stateIntMaybeInt'         = nmap -#-     ()                           <##> NT (Just . runIdentity) -#- ()   $ stateIntIdentityInt+-- >>> let stateIntIdentityString'   = nmap -#-     ()                           -#-  ()                      <#> show $ stateIntIdentityInt+-- >>> let stateIntIdentityInt'''    = nmap -#-     ()                           -#-  ()                      -#- ()   $ stateIntIdentityInt+-- >>> runStateT stateIntIdentityInt' 4+-- Identity (2,4)+-- >>> runStateT stateIntMaybeInt 4+-- Just (2,4)+-- >>> runStateT stateIntIdentityString 4+-- Identity ("2",4)+-- >>> runStateT stateIntIdentityInt'' 4+-- Identity (2,4)+-- >>> runStateT stateStringMaybeInt "four"+-- Just (2,"....")+-- >>> runStateT stateStringIdentityString "four"+-- Identity ("2","....")+-- >>> runStateT stateStringIdentityInt "four"+-- Identity (2,"....")+-- >>> runStateT stateIntMaybeString 4+-- Just ("2",4)+-- >>> runStateT stateIntMaybeInt' 4+-- Just (2,4)+-- >>> runStateT stateIntIdentityString' 4+-- Identity ("2",4)+-- >>> runStateT stateIntIdentityInt''' 4+-- Identity (2,4)+instance NFunctor StateT where+  type VarianceStack StateT = InvariantT (Covariant1T (CovariantT (->)))+  nmap = InvariantT $ \(f1, f1')+      -> Covariant1T $ \f2+      -> CovariantT $ \f3+      -> \body+      -> StateT $ \s'+      -> fmap (f3 *** f1) $ unwrapNT f2 $ runStateT body $ f1' s'++-- $+-- >>> let writerIntIdentityInt    = do {tell [4]; lift $ Identity 2}+-- >>> let writerIntIdentityString = nmap                                       <#> show $ writerIntIdentityInt+-- >>> let writerIntMaybeString    = nmap          <##> NT (Just . runIdentity) <#> show $ writerIntIdentityInt+-- >>> let writerStringMaybeString = nmap <#> show <##> NT (Just . runIdentity) <#> show $ writerIntIdentityInt+-- >>> runWriterT writerIntIdentityInt+-- Identity (2,[4])+-- >>> runWriterT writerIntIdentityString+-- Identity ("2",[4])+-- >>> runWriterT writerIntMaybeString+-- Just ("2",[4])+-- >>> runWriterT writerStringMaybeString+-- Just ("2","[4]")+--+-- >>> let writerIntIdentityInt'      = nmap                                                                    -#- ()   $ writerIntIdentityInt+-- >>> let writerIntMaybeInt          = nmap                                       <##> NT (Just . runIdentity) -#- ()   $ writerIntIdentityInt+-- >>> let writerIntIdentityString    = nmap                                       -#-  ()                      <#> show $ writerIntIdentityInt+-- >>> let writerIntIdentityInt''     = nmap                                       -#-  ()                      -#- ()   $ writerIntIdentityInt+-- >>> let writerStringMaybeInt       = nmap <#> show <##> NT (Just . runIdentity) -#- ()   $ writerIntIdentityInt+-- >>> let writerStringIdentityString = nmap <#> show -#-  ()                      <#> show $ writerIntIdentityInt+-- >>> let writerStringIdentityInt    = nmap <#> show -#-  ()                      -#- ()   $ writerIntIdentityInt+-- >>> let writerIntMaybeString       = nmap -#- ()   <##> NT (Just . runIdentity) <#> show $ writerIntIdentityInt+-- >>> let writerIntMaybeInt'         = nmap -#- ()   <##> NT (Just . runIdentity) -#- ()   $ writerIntIdentityInt+-- >>> let writerIntIdentityString'   = nmap -#- ()   -#-  ()                      <#> show $ writerIntIdentityInt+-- >>> let writerIntIdentityInt'''    = nmap -#- ()   -#-  ()                      -#- ()   $ writerIntIdentityInt+-- >>> runWriterT writerIntIdentityInt'+-- Identity (2,[4])+-- >>> runWriterT writerIntMaybeInt+-- Just (2,[4])+-- >>> runWriterT writerIntIdentityString+-- Identity ("2",[4])+-- >>> runWriterT writerIntIdentityInt''+-- Identity (2,[4])+-- >>> runWriterT writerStringMaybeInt+-- Just (2,"[4]")+-- >>> runWriterT writerStringIdentityString+-- Identity ("2","[4]")+-- >>> runWriterT writerStringIdentityInt+-- Identity (2,"[4]")+-- >>> runWriterT writerIntMaybeString+-- Just ("2",[4])+-- >>> runWriterT writerIntMaybeInt'+-- Just (2,[4])+-- >>> runWriterT writerIntIdentityString'+-- Identity ("2",[4])+-- >>> runWriterT writerIntIdentityInt'''+-- Identity (2,[4])+instance NFunctor WriterT where+  type VarianceStack WriterT = CovariantT (Covariant1T (CovariantT (->)))+  nmap = CovariantT $ \f1+      -> Covariant1T $ \f2+      -> CovariantT $ \f3+      -> \body+      -> WriterT+       $ fmap (f3 *** f1) $ unwrapNT f2 $ runWriterT body++-- $+-- >>> let myConst = Const "foo" :: Const String Double+-- >>> (nmap            👻#👻 () $ myConst) <&> length+-- Const "foo"+-- >>> (nmap <#> length 👻#👻 () $ myConst) <&> length+-- Const 3+--+-- >>> (nmap            -#-   () $ myConst)+-- Const "foo"+-- >>> (nmap <#> length -#-   () $ myConst)+-- Const 3+-- >>> (nmap -#- ()     👻#👻 () $ myConst) <&> length+-- Const "foo"+-- >>> (nmap -#- ()     -#-   () $ myConst)+-- Const "foo"+instance NFunctor Const where+  type VarianceStack Const = CovariantT (PhantomvariantT (->))+  nmap = CovariantT $ \f1+      -> PhantomvariantT $ \()+      -> \(Const a1)+      -> Const (f1 a1)++ -- | -- For kind @*@, 'nmap' must be the identity function. If 'Bifunctor' and -- 'Functor' correspond to binary and unary functors, this corresponds to a@@ -93,185 +472,201 @@ -- >>> nmap () -- () instance NFunctor () where+  type VarianceStack () = (->)   nmap = id  instance NFunctor Identity where-  nmap = NMap1 $ \f1+  type VarianceStack Identity = CovariantT (->)+  nmap = CovariantT $ \f1       -> \(Identity x1)       -> Identity (f1 x1)  instance NFunctor (,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2+  type VarianceStack (,) = CovariantT (CovariantT (->))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2       -> \(x1,x2)       -> (f1 x1, f2 x2)  instance NFunctor (,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3+  type VarianceStack (,,) = CovariantT (CovariantT (CovariantT (->)))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3       -> \(x1,x2,x3)       -> (f1 x1, f2 x2, f3 x3)  instance NFunctor (,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4+  type VarianceStack (,,,) = CovariantT (CovariantT (CovariantT (CovariantT (->))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4       -> \(x1,x2,x3,x4)       -> (f1 x1, f2 x2, f3 x3, f4 x4)  instance NFunctor (,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5+  type VarianceStack (,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5       -> \(x1,x2,x3,x4,x5)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5)  instance NFunctor (,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6+  type VarianceStack (,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6       -> \(x1,x2,x3,x4,x5,x6)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6)  instance NFunctor (,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7+  type VarianceStack (,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7       -> \(x1,x2,x3,x4,x5,x6,x7)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7)  instance NFunctor (,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8+  type VarianceStack (,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8       -> \(x1,x2,x3,x4,x5,x6,x7,x8)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8)  instance NFunctor (,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9+  type VarianceStack (,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9)  instance NFunctor (,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10+  type VarianceStack (,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10)  instance NFunctor (,,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10-      -> NMap1 $ \f11+  type VarianceStack (,,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10+      -> CovariantT $ \f11       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10, f11 x11)  instance NFunctor (,,,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10-      -> NMap1 $ \f11-      -> NMap1 $ \f12+  type VarianceStack (,,,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->))))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10+      -> CovariantT $ \f11+      -> CovariantT $ \f12       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10, f11 x11, f12 x12)  instance NFunctor (,,,,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10-      -> NMap1 $ \f11-      -> NMap1 $ \f12-      -> NMap1 $ \f13+  type VarianceStack (,,,,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10+      -> CovariantT $ \f11+      -> CovariantT $ \f12+      -> CovariantT $ \f13       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10, f11 x11, f12 x12, f13 x13)  instance NFunctor (,,,,,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10-      -> NMap1 $ \f11-      -> NMap1 $ \f12-      -> NMap1 $ \f13-      -> NMap1 $ \f14+  type VarianceStack (,,,,,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->))))))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10+      -> CovariantT $ \f11+      -> CovariantT $ \f12+      -> CovariantT $ \f13+      -> CovariantT $ \f14       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10, f11 x11, f12 x12, f13 x13, f14 x14)  instance NFunctor (,,,,,,,,,,,,,,) where-  nmap = NMap1 $ \f1-      -> NMap1 $ \f2-      -> NMap1 $ \f3-      -> NMap1 $ \f4-      -> NMap1 $ \f5-      -> NMap1 $ \f6-      -> NMap1 $ \f7-      -> NMap1 $ \f8-      -> NMap1 $ \f9-      -> NMap1 $ \f10-      -> NMap1 $ \f11-      -> NMap1 $ \f12-      -> NMap1 $ \f13-      -> NMap1 $ \f14-      -> NMap1 $ \f15+  type VarianceStack (,,,,,,,,,,,,,,) = CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (CovariantT (->)))))))))))))))+  nmap = CovariantT $ \f1+      -> CovariantT $ \f2+      -> CovariantT $ \f3+      -> CovariantT $ \f4+      -> CovariantT $ \f5+      -> CovariantT $ \f6+      -> CovariantT $ \f7+      -> CovariantT $ \f8+      -> CovariantT $ \f9+      -> CovariantT $ \f10+      -> CovariantT $ \f11+      -> CovariantT $ \f12+      -> CovariantT $ \f13+      -> CovariantT $ \f14+      -> CovariantT $ \f15       -> \(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15)       -> (f1 x1, f2 x2, f3 x3, f4 x4, f5 x5, f6 x6, f7 x7, f8 x8, f9 x9, f10 x10, f11 x11, f12 x12, f13 x13, f14 x14, f15 x15) 
test/doctests.hs view
@@ -1,1 +1,10 @@-{-# OPTIONS_GHC -F -pgmF doctest-discover #-}+module Main where++import Build_doctests (flags, pkgs, module_sources)+import Test.DocTest (doctest)++main :: IO ()+main = do+    doctest args+  where+    args = flags ++ pkgs ++ module_sources