diff --git a/functor-utils.cabal b/functor-utils.cabal
--- a/functor-utils.cabal
+++ b/functor-utils.cabal
@@ -1,32 +1,35 @@
-name: functor-utils
-version: 1.1
-cabal-version: >=1.10
-build-type: Simple
-license: Apache-2.0
-license-file: LICENSE
-copyright: Copyright (C) 2015 Wojciech Danilo
-maintainer: Wojciech Danilo <wojciech.danilo@gmail.com>
-stability: stable
-homepage: https://github.com/wdanilo/functor-utils
-bug-reports: https://github.com/wdanilo/functor-utils/issues
-synopsis: Collection of functor utilities, providing handy operators, like generalization of (.).
-category: Text
-author: Wojciech Danilo
+-- This file has been generated from package.yaml by hpack version 0.20.0.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 34760b4dc30c57297b2d5a92cb7bdaeab0f9c2913e60afca1589d0830552c190
 
-library
-    exposed-modules:
-        Data.Functor.Utils
-    build-depends:
-        base >=4.6 && <4.9,
-        ghc-prim >=0.4.0.0
-    default-language: Haskell2010
-    default-extensions: ConstraintKinds DataKinds DefaultSignatures
-                        DeriveDataTypeable DeriveFoldable DeriveFunctor DeriveGeneric
-                        DeriveTraversable DoAndIfThenElse EmptyDataDecls FlexibleContexts
-                        FlexibleInstances GeneralizedNewtypeDeriving InstanceSigs
-                        LambdaCase MultiParamTypeClasses OverloadedStrings
-                        StandaloneDeriving TemplateHaskell TupleSections TypeOperators
-                        ViewPatterns TypeFamilies
-    hs-source-dirs: src
-    ghc-options: -Wall -O2
+name:           functor-utils
+version:        1.17.1
+synopsis:       Collection of functor utilities, providing handy operators, like generalization of (.).
+category:       Data
+stability:      experimental
+homepage:       https://github.com/luna/functor-utils
+bug-reports:    https://github.com/luna/functor-utils/issues
+author:         Luna Team
+maintainer:     Wojciech Danilo <wojciech.danilo@luna-lang.org>
+copyright:      Copyright (C) 2018 Luna Team
+license:        Apache-2.0
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
 
+library
+  hs-source-dirs:
+      src
+  default-extensions: AllowAmbiguousTypes ApplicativeDo BangPatterns BinaryLiterals ConstraintKinds DataKinds DefaultSignatures DeriveDataTypeable DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable DoAndIfThenElse DuplicateRecordFields EmptyDataDecls FlexibleContexts FlexibleInstances FunctionalDependencies GeneralizedNewtypeDeriving InstanceSigs LambdaCase MonadComprehensions MultiWayIf NamedWildCards NegativeLiterals NoImplicitPrelude NumDecimals OverloadedLabels PackageImports QuasiQuotes PatternSynonyms RankNTypes RecursiveDo ScopedTypeVariables StandaloneDeriving TemplateHaskell TupleSections TypeApplications TypeFamilies TypeFamilyDependencies TypeOperators UnicodeSyntax ViewPatterns LiberalTypeSynonyms RelaxedPolyRec
+  ghc-options: -Wall -O2
+  build-depends:
+      base >=4.10 && <4.12
+    , ghc-prim
+    , lens
+  exposed-modules:
+      Data.Functor.Utils
+  other-modules:
+      Paths_functor_utils
+  default-language: Haskell2010
diff --git a/src/Data/Functor/Utils.hs b/src/Data/Functor/Utils.hs
--- a/src/Data/Functor/Utils.hs
+++ b/src/Data/Functor/Utils.hs
@@ -1,103 +1,123 @@
 {-# LANGUAGE NoMonomorphismRestriction #-}
 
-module Data.Functor.Utils where
+module Data.Functor.Utils (module Data.Functor.Utils, module X) where
 
 import Prelude hiding ((.))
-import GHC.Prim (Constraint)
+import GHC.Exts (Constraint)
+import Data.Traversable (mapM)
+import Data.Functor.Compose as X (Compose(Compose), getCompose)
+import Control.Lens
 
--- Nested fmaps
 
+-- === Multi-constraint type families === --
+
+type family Functors lst :: Constraint where
+    Functors '[]       = ()
+    Functors (f ': fs) = (Functor f, Functors fs)
+
+type family Applicatives lst :: Constraint where
+    Applicatives '[]       = ()
+    Applicatives (f ': fs) = (Applicative f, Applicatives fs)
+
+
+-- === Nested fmaps === --
+
+fmap0                                  ::                               (a -> b) ->                    a     ->                    b
+(.)                          , (∘)     :: Functor  f1                => (a -> b) ->                 f1 a     ->                 f1 b
+fmap2, (.:)  , (<<$>>)       , (∘∘)    :: Functors '[f1,f2]          => (a -> b) ->             f2 (f1 a)    ->             f2 (f1 b)
+fmap3, (.:.) , (<<<$>>>)     , (∘∘∘)   :: Functors '[f1,f2,f3]       => (a -> b) ->         f3 (f2 (f1 a))   ->         f3 (f2 (f1 b))
+fmap4, (.::) , (<<<<$>>>>)   , (∘∘∘∘)  :: Functors '[f1,f2,f3,f4]    => (a -> b) ->     f4 (f3 (f2 (f1 a)))  ->     f4 (f3 (f2 (f1 b)))
+fmap5, (.::.), (<<<<<$>>>>>) , (∘∘∘∘∘) :: Functors '[f1,f2,f3,f4,f5] => (a -> b) -> f5 (f4 (f3 (f2 (f1 a)))) -> f5 (f4 (f3 (f2 (f1 b))))
+
+fmap0 = ($)        ; {-# INLINE fmap0 #-}
 fmap1 = fmap       ; {-# INLINE fmap1 #-}
 fmap2 = fmap.fmap  ; {-# INLINE fmap2 #-}
 fmap3 = fmap.fmap2 ; {-# INLINE fmap3 #-}
 fmap4 = fmap.fmap3 ; {-# INLINE fmap4 #-}
 fmap5 = fmap.fmap4 ; {-# INLINE fmap5 #-}
-fmap6 = fmap.fmap5 ; {-# INLINE fmap6 #-}
-fmap7 = fmap.fmap6 ; {-# INLINE fmap7 #-}
-fmap8 = fmap.fmap7 ; {-# INLINE fmap8 #-}
-fmap9 = fmap.fmap8 ; {-# INLINE fmap9 #-}
 
--- Dots
+-- === Dot operators === --
 
-dot1 = (.)         ; {-# INLINE dot1 #-}
-dot2 = dot1 . dot1 ; {-# INLINE dot2 #-}
-dot3 = dot1 . dot2 ; {-# INLINE dot3 #-}
-dot4 = dot1 . dot3 ; {-# INLINE dot4 #-}
-dot5 = dot1 . dot4 ; {-# INLINE dot5 #-}
-dot6 = dot1 . dot5 ; {-# INLINE dot6 #-}
-dot7 = dot1 . dot6 ; {-# INLINE dot7 #-}
-dot8 = dot1 . dot7 ; {-# INLINE dot8 #-}
-dot9 = dot1 . dot8 ; {-# INLINE dot9 #-}
+infixr 9 .
+infixr 8 .:
+infixr 8 .:.
+infixr 8 .::
+infixr 8 .::.
+(.)      = fmap  ; {-# INLINE (.)      #-}
+(.:)     = fmap2 ; {-# INLINE (.:)     #-}
+(.:.)    = fmap3 ; {-# INLINE (.:.)    #-}
+(.::)    = fmap4 ; {-# INLINE (.::)    #-}
+(.::.)   = fmap5 ; {-# INLINE (.::.)   #-}
 
--- Operators
+-- === UTF8 operators === --
 
 infixr 9 ∘
-infixr 9 ∘∘
-infixr 9 ∘∘∘
-infixr 9 ∘∘∘∘
-infixr 9 ∘∘∘∘∘
-(∘)      = fmap ; {-# INLINE (∘)     #-}
-(∘∘)     = dot2 ; {-# INLINE (∘∘)    #-}
-(∘∘∘)    = dot3 ; {-# INLINE (∘∘∘)   #-}
-(∘∘∘∘)   = dot4 ; {-# INLINE (∘∘∘∘)  #-}
-(∘∘∘∘∘)  = dot5 ; {-# INLINE (∘∘∘∘∘) #-}
+infixr 8 ∘∘
+infixr 8 ∘∘∘
+infixr 8 ∘∘∘∘
+infixr 8 ∘∘∘∘∘
+(∘)      = fmap  ; {-# INLINE (∘)     #-}
+(∘∘)     = fmap2 ; {-# INLINE (∘∘)    #-}
+(∘∘∘)    = fmap3 ; {-# INLINE (∘∘∘)   #-}
+(∘∘∘∘)   = fmap4 ; {-# INLINE (∘∘∘∘)  #-}
+(∘∘∘∘∘)  = fmap5 ; {-# INLINE (∘∘∘∘∘) #-}
 
-infixr 9 .
-infixr 9 .:
-infixr 9 .:.
-infixr 9 .::
-infixr 9 .::.
-infixr 9 .:::
-infixr 9 .:::.
-infixr 9 .::::
-infixr 9 .::::.
-(.) :: (Functor f) => (a -> b) -> f a -> f b
-(.)      = fmap ; {-# INLINE (.)      #-}
-(.:)     = dot2 ; {-# INLINE (.:)     #-}
-(.:.)    = dot3 ; {-# INLINE (.:.)    #-}
-(.::)    = dot4 ; {-# INLINE (.::)    #-}
-(.::.)   = dot5 ; {-# INLINE (.::.)   #-}
-(.:::)   = dot6 ; {-# INLINE (.:::)   #-}
-(.:::.)  = dot7 ; {-# INLINE (.:::.)  #-}
-(.::::)  = dot8 ; {-# INLINE (.::::)  #-}
-(.::::.) = dot9 ; {-# INLINE (.::::.) #-}
+-- === Applicative operators === --
 
+infixl 4 <<$>>
+infixl 4 <<<$>>>
+infixl 4 <<<<$>>>>
+infixl 4 <<<<<$>>>>>
+(<<$>>)       = fmap2 ; {-# INLINE (<<$>>)       #-}
+(<<<$>>>)     = fmap3 ; {-# INLINE (<<<$>>>)     #-}
+(<<<<$>>>>)   = fmap4 ; {-# INLINE (<<<<$>>>>)   #-}
+(<<<<<$>>>>>) = fmap5 ; {-# INLINE (<<<<<$>>>>>) #-}
 
+infixl 4 <<*>>
+infixl 4 <<<*>>>
+infixl 4 <<<<*>>>>
+infixl 4 <<<<<*>>>>>
+(<<*>>)       :: Applicatives '[f1, f2]             =>             f2 (f1 (a -> b))    ->             f2 (f1 a)    ->             f2 (f1 b)
+(<<<*>>>)     :: Applicatives '[f1, f2, f3]         =>         f3 (f2 (f1 (a -> b)))   ->         f3 (f2 (f1 a))   ->         f3 (f2 (f1 b))
+(<<<<*>>>>)   :: Applicatives '[f1, f2, f3, f4]     =>     f4 (f3 (f2 (f1 (a -> b))))  ->     f4 (f3 (f2 (f1 a)))  ->     f4 (f3 (f2 (f1 b)))
+(<<<<<*>>>>>) :: Applicatives '[f1, f2, f3, f4, f5] => f5 (f4 (f3 (f2 (f1 (a -> b))))) -> f5 (f4 (f3 (f2 (f1 a)))) -> f5 (f4 (f3 (f2 (f1 b))))
+(<<*>>)       = (<*>) . fmap (<*>)       ; {-# INLINE (<<*>>)       #-}
+(<<<*>>>)     = (<*>) . fmap (<<*>>)     ; {-# INLINE (<<<*>>>)     #-}
+(<<<<*>>>>)   = (<*>) . fmap (<<<*>>>)   ; {-# INLINE (<<<<*>>>>)   #-}
+(<<<<<*>>>>>) = (<*>) . fmap (<<<<*>>>>) ; {-# INLINE (<<<<<*>>>>>) #-}
 
-infixl 4 <∘>
-infixl 4 <∘∘>
-infixl 4 <∘∘∘>
-infixl 4 <∘∘∘∘>
-infixl 4 <∘∘∘∘∘>
-f <∘>     a = fmap  f ∘     a ; {-# INLINE (<∘>)     #-}
-f <∘∘>    a = fmap  f ∘∘    a ; {-# INLINE (<∘∘>)    #-}
-f <∘∘∘>   a = fmap  f ∘∘∘   a ; {-# INLINE (<∘∘∘>)   #-}
-f <∘∘∘∘>  a = fmap  f ∘∘∘∘  a ; {-# INLINE (<∘∘∘∘>)  #-}
-f <∘∘∘∘∘> a = fmap  f ∘∘∘∘∘ a ; {-# INLINE (<∘∘∘∘∘>) #-}
 
+-- === Functors remembering call args === --
 
+infixl 4 |$
+infixl 4 $|
+(|$) :: (a -> b) -> a -> (a, b)
+($|) :: (a -> b) -> a -> (b, a)
+f |$ a = (a, f a) ; {-# INLINE (|$) #-}
+f $| a = (f a, a) ; {-# INLINE ($|) #-}
 
-f <<∘>> a = fmap2 f ∘  a
+infixl 4 <|$>
+infixl 4 <$|>
+(<|$>) :: Functor f => (a -> b) -> f a -> f (a, b)
+(<$|>) :: Functor f => (a -> b) -> f a -> f (b, a)
+f <|$> a = (f |$) <$> a ; {-# INLINE (<|$>) #-}
+f <$|> a = (f $|) <$> a ; {-# INLINE (<$|>) #-}
 
-infixl 4 <<$>>
-f <<$>> a = fmap f <$> a
 
-{-# INLINE (<<∘>>) #-}
-{-# INLINE (<<$>>) #-}
+-- === Functor composition === --
 
--- nested lenses
--- | following functions are usefull when operating on nested structures with lenses, for example
--- | given function foo :: a -> m (n a) and a lens l :: Lens' x a, we can use 
--- | nested l foo to get signature of x -> m (n x) 
+composed :: Iso' (f (g a)) (Compose f g a)
+composed = iso Compose getCompose ; {-# INLINE composed #-}
 
-newtype NestedFunctor m n a = NestedFunctor { fromNestedFunctor :: m (n a)} deriving (Show)
-instance (Functor m, Functor n) => Functor (NestedFunctor m n) where fmap f = NestedFunctor . (fmap $ fmap f) . fromNestedFunctor
 
---nested :: (Functor m, Functor n) => Lens a b c d -> (c -> m (n d)) -> (a -> m (n b))
-nested l f = fromNestedFunctor . l (fmap NestedFunctor f)
-{-# INLINE nested #-}
+-- FIXME[WD]: Think if lenses doesnt provide any counterpart to it.
+-- === Nested functors === --
 
+-- nested lenses
+-- | following functions are usefull when operating on nested structures with lenses, for example
+-- | given function foo :: a -> m (n a) and a lens l :: Lens' x a, we can use
+-- | nested l foo to get signature of x -> m (n x)
 
-type family Functors lst :: Constraint where 
-    Functors '[]       = ()
-    Functors (f ': fs) = (Functor f, Functors fs)
+-- nested :: (Functor m, Functor n) => Lens a b c d -> (c -> m (n d)) -> (a -> m (n b))
+-- nested :: (Functor f10, Functor f0) => (f0 (Compose m1 n1 a1) -> f10 (Compose m n a)) -> f0 (m1 (n1 a1)) -> f10 (m (n a))
+nested l f = getCompose . l (fmap Compose f) ; {-# INLINE nested #-}
