diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,3 +7,12 @@
 * Define `Invariant` instance for `Constant` datatype
 * Remove all `Invariant` methods except `invmap`
 * Extract `Junction` module from `Basis`
+
+# 0.1.2
+* Define `Pipeline` control flow paradigm
+* Split `Structure` modules on `Property` and `Concrete`
+* Define `Hollow` type class for handling empty structures
+* Extract `Nonempty` into a separated module
+* Define `Graph` concrete structure
+* Define infix `:-.` type operator for Lens
+* Define `Object` instances for `Product` datatype
diff --git a/Pandora/Paradigm/Basis/Product.hs b/Pandora/Paradigm/Basis/Product.hs
--- a/Pandora/Paradigm/Basis/Product.hs
+++ b/Pandora/Paradigm/Basis/Product.hs
@@ -6,6 +6,13 @@
 import Pandora.Pattern.Functor.Extendable (Extendable ((=>>)))
 import Pandora.Pattern.Functor.Comonad (Comonad)
 import Pandora.Pattern.Functor.Adjoint (Adjoint (phi, psi))
+import Pandora.Pattern.Object.Setoid (Setoid ((==)), (&&))
+import Pandora.Pattern.Object.Semigroup (Semigroup ((<>)))
+import Pandora.Pattern.Object.Monoid (Monoid (unit))
+import Pandora.Pattern.Object.Ringoid (Ringoid ((><)))
+import Pandora.Pattern.Object.Semilattice (Infimum ((/\)), Supremum ((\/)))
+import Pandora.Pattern.Object.Lattice (Lattice)
+import Pandora.Pattern.Object.Group (Group (inverse))
 
 infixr 1 :*
 
@@ -27,6 +34,29 @@
 instance Adjoint (Product a) ((->) a) where
 	phi f x y = f $ y :* x
 	psi f (y :* x) = f x y
+
+instance (Setoid a, Setoid b) => Setoid (Product a b) where
+	(x :* y) == (x' :* y') = x == x' && y == y'
+
+instance (Semigroup a, Semigroup b) => Semigroup (Product a b) where
+	(x :* y) <> (x' :* y') = x <> x' :* y <> y'
+
+instance (Monoid a, Monoid b) => Monoid (Product a b) where
+	unit = unit :* unit
+
+instance (Ringoid a, Ringoid b) => Ringoid (Product a b) where
+	(x :* y) >< (x' :* y') = x >< x' :* y >< y'
+
+instance (Infimum a, Infimum b) => Infimum (Product a b) where
+	(x :* y) /\ (x' :* y') = x /\ x' :* y /\ y'
+
+instance (Supremum a, Supremum b) => Supremum (Product a b) where
+	(x :* y) \/ (x' :* y') = x \/ x' :* y \/ y'
+
+instance (Lattice a, Lattice b) => Lattice (Product a b) where
+
+instance (Group a, Group b) => Group (Product a b) where
+	inverse (x :* y) = inverse x :* inverse y
 
 delta :: a -> a :* a
 delta x = x :* x
diff --git a/Pandora/Paradigm/Controlflow.hs b/Pandora/Paradigm/Controlflow.hs
--- a/Pandora/Paradigm/Controlflow.hs
+++ b/Pandora/Paradigm/Controlflow.hs
@@ -1,3 +1,4 @@
 module Pandora.Paradigm.Controlflow (module Exports) where
 
+import Pandora.Paradigm.Controlflow.Pipeline as Exports
 import Pandora.Paradigm.Controlflow.Observable as Exports
diff --git a/Pandora/Paradigm/Controlflow/Pipeline.hs b/Pandora/Paradigm/Controlflow/Pipeline.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Controlflow/Pipeline.hs
@@ -0,0 +1,61 @@
+module Pandora.Paradigm.Controlflow.Pipeline (Pipeline, await, yield, finish, impact, (=*=), pipeline) where
+
+import Pandora.Core.Morphism (($))
+import Pandora.Paradigm.Basis.Continuation (Continuation (Continuation, continue))
+import Pandora.Pattern.Functor.Covariant (Covariant ((<$>)))
+import Pandora.Pattern.Functor.Contravariant (Contravariant ((>$<)))
+import Pandora.Pattern.Functor.Pointable (Pointable (point))
+import Pandora.Pattern.Functor.Bindable (Bindable ((>>=)))
+
+newtype Producer i t r = Producer { produce :: Consumer i t r -> t r }
+
+newtype Consumer o t r = Consumer { consume :: o -> Producer o t r -> t r }
+
+newtype Pipe i o r t a = Pipe { pipe :: Producer i t r -> Consumer o t r -> t r }
+
+instance Covariant (Pipe i o r t) where
+	f <$> Pipe p = Pipe p
+
+instance Contravariant (Pipe i o r t) where
+	f >$< Pipe p = Pipe p
+
+type Pipeline i o t a r = Continuation r (Pipe i o r t) a
+
+pause :: (() -> Pipe i o r t a) -> Producer i t r -> Producer o t r
+pause next ik = Producer $ \ok -> (pipe $ next ()) ik ok
+
+suspend :: (i -> Pipe i o r t a) -> Consumer o t r -> Consumer i t r
+suspend next ok = Consumer $ \v ik -> pipe (next v) ik ok
+
+-- | Take incoming value from pipeline
+await :: Pipeline i o t i r
+await = Continuation $ \next -> Pipe $ \i o -> produce i (suspend next o)
+
+-- | Give a value to the future consuming
+yield :: o -> Pipeline i o t () r
+yield v = Continuation $ \next -> Pipe $ \i o -> consume o v (pause next i)
+
+-- | Pipeline that does nothing
+finish :: Pointable t => Pipeline i o t () ()
+finish = Continuation $ \_ -> Pipe $ \_ _ -> point ()
+
+-- | Do some effectful computation within pipeline
+impact :: Bindable t => t a -> Pipeline i o t a a
+impact action = Continuation $ \next -> Pipe $ \i o -> action >>= \x -> pipe (next x) i o
+
+-- | Compose two pipelines into one
+(=*=) :: forall i e a o t . Pointable t => Pipeline i e t () () -> Pipeline e o t () () -> Pipeline i o t a ()
+p =*= q = Continuation $ \_ -> Pipe $ \i o -> pipe (continue q end) (pause (\() -> continue p end) i) o where
+
+	end :: b -> Pipe c d () t ()
+	end _ = Pipe $ \_ _ -> point ()
+
+-- | Run pipeline and get result
+pipeline :: Pointable t => Pipeline i o t r r -> t r
+pipeline p = pipe (continue p (\r -> Pipe $ \_ _ -> point r)) i o where
+
+	i :: Producer i t r
+	i = Producer $ \o -> produce i o
+
+	o :: Consumer o t r
+	o = Consumer $ \v i -> consume o v i
diff --git a/Pandora/Paradigm/Inventory/Optics.hs b/Pandora/Paradigm/Inventory/Optics.hs
--- a/Pandora/Paradigm/Inventory/Optics.hs
+++ b/Pandora/Paradigm/Inventory/Optics.hs
@@ -1,10 +1,13 @@
-module Pandora.Paradigm.Inventory.Optics (Lens, (|>), view, set, over, (^.), (.~), (%~)) where
+module Pandora.Paradigm.Inventory.Optics (Lens, type (:-.), (|>), view, set, over, (^.), (.~), (%~)) where
 
 import Pandora.Core.Morphism ((.), ($))
 import Pandora.Paradigm.Basis.Identity (Identity)
 import Pandora.Paradigm.Inventory.Storage (Storage (Storage), access, position, retrofit)
 import Pandora.Pattern.Functor.Covariant (Covariant ((<$)))
 import Pandora.Pattern.Functor.Extractable (Extractable (extract))
+
+infixr 0 :-.
+type (:-.) src tgt = Lens src tgt
 
 type Lens src tgt = src -> Storage tgt Identity src
 
diff --git a/Pandora/Paradigm/Inventory/Stateful.hs b/Pandora/Paradigm/Inventory/Stateful.hs
--- a/Pandora/Paradigm/Inventory/Stateful.hs
+++ b/Pandora/Paradigm/Inventory/Stateful.hs
@@ -1,4 +1,4 @@
-module Pandora.Paradigm.Inventory.Stateful (Stateful (..), State, get, modify, put) where
+module Pandora.Paradigm.Inventory.Stateful (Stateful (..), State, get, modify, put, fold) where
 
 import Pandora.Core.Functor (type (:.:))
 import Pandora.Core.Morphism ((.), ($))
diff --git a/Pandora/Paradigm/Structure.hs b/Pandora/Paradigm/Structure.hs
--- a/Pandora/Paradigm/Structure.hs
+++ b/Pandora/Paradigm/Structure.hs
@@ -1,9 +1,4 @@
-module Pandora.Paradigm.Structure (Nonempty, module Exports) where
-
-import Pandora.Paradigm.Structure.Stack as Exports
-
-import Pandora.Paradigm.Basis.Cofree (Cofree)
-import Pandora.Paradigm.Junction.Transformer (type (:>:))
+module Pandora.Paradigm.Structure (module Exports) where
 
-type family Nonempty structure a :: * where
-	Nonempty (Cofree :>: t) a = Cofree t a
+import Pandora.Paradigm.Structure.Concrete as Exports
+import Pandora.Paradigm.Structure.Property as Exports
diff --git a/Pandora/Paradigm/Structure/Concrete.hs b/Pandora/Paradigm/Structure/Concrete.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Concrete.hs
@@ -0,0 +1,4 @@
+module Pandora.Paradigm.Structure.Concrete (module Exports) where
+
+import Pandora.Paradigm.Structure.Concrete.Graph as Exports
+import Pandora.Paradigm.Structure.Concrete.Stack as Exports
diff --git a/Pandora/Paradigm/Structure/Concrete/Graph.hs b/Pandora/Paradigm/Structure/Concrete/Graph.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Concrete/Graph.hs
@@ -0,0 +1,21 @@
+module Pandora.Paradigm.Structure.Concrete.Graph (Graph, loose) where
+
+import Pandora.Core.Morphism ((.))
+import Pandora.Paradigm.Basis.Edges (Edges (Empty, Connect, Overlay))
+import Pandora.Paradigm.Basis.Cofree (Cofree ((:<)))
+import Pandora.Paradigm.Junction.Transformer (Y (Y), type (:>:))
+import Pandora.Paradigm.Inventory.Stateful (fold)
+import Pandora.Paradigm.Structure.Property.Hollow (Hollow (hollow))
+import Pandora.Pattern.Functor.Traversable (Traversable)
+
+-- | Acyclic graph structure without loops
+type Graph a = (Cofree :>: Edges) a
+
+instance Hollow Edges where
+	hollow result _ (Y Empty) = result
+	hollow _ f (Y (Connect struct)) = f struct
+	hollow _ f (Y (Overlay struct)) = f struct
+
+-- | Transform any traversable structure into all loose edges graph
+loose :: Traversable t => t a -> Graph a
+loose = Y . fold Empty (\x -> Overlay . (:<) x)
diff --git a/Pandora/Paradigm/Structure/Concrete/Stack.hs b/Pandora/Paradigm/Structure/Concrete/Stack.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Concrete/Stack.hs
@@ -0,0 +1,34 @@
+module Pandora.Paradigm.Structure.Concrete.Stack (Stack, push, top, pop, linearize) where
+
+import Pandora.Core.Morphism ((.), ($))
+import Pandora.Paradigm.Basis.Cofree (Cofree ((:<)), unwrap)
+import Pandora.Paradigm.Basis.Maybe (Maybe (Just, Nothing))
+import Pandora.Paradigm.Junction.Transformer (Y (Y, y), type (:>:))
+import Pandora.Paradigm.Inventory.Stateful (fold)
+import Pandora.Paradigm.Structure.Property.Hollow (Hollow (hollow))
+import Pandora.Pattern.Functor.Covariant (Covariant ((<$>)))
+import Pandora.Pattern.Functor.Pointable (Pointable (point))
+import Pandora.Pattern.Functor.Extractable (Extractable (extract))
+import Pandora.Pattern.Functor.Alternative (Alternative ((<+>)))
+import Pandora.Pattern.Functor.Traversable (Traversable)
+import Pandora.Pattern.Functor.Bindable (Bindable ((>>=)))
+
+-- | Linear data structure that serves as a collection of elements
+type Stack = (Cofree :>: Maybe)
+
+instance Hollow Maybe where
+	hollow result _ (Y Nothing) = result
+	hollow _ f (Y (Just struct)) = f struct
+
+push :: a -> Stack a -> Stack a
+push x (Y struct) = (Y $ (:<) x . Just <$> struct) <+> point x
+
+top :: Stack a -> Maybe a
+top (Y struct) = extract <$> struct
+
+pop :: Stack a -> Stack a
+pop (Y struct) = Y $ struct >>= unwrap
+
+-- | Transform any traversable structure into a stack
+linearize :: Traversable t => t a -> Stack a
+linearize = Y . fold Nothing (\x -> Just . (:<) x)
diff --git a/Pandora/Paradigm/Structure/Property.hs b/Pandora/Paradigm/Structure/Property.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Property.hs
@@ -0,0 +1,4 @@
+module Pandora.Paradigm.Structure.Property (module Exports) where
+
+import Pandora.Paradigm.Structure.Property.Nonempty as Exports
+import Pandora.Paradigm.Structure.Property.Hollow as Exports
diff --git a/Pandora/Paradigm/Structure/Property/Hollow.hs b/Pandora/Paradigm/Structure/Property/Hollow.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Property/Hollow.hs
@@ -0,0 +1,8 @@
+module Pandora.Paradigm.Structure.Property.Hollow (Hollow (..)) where
+
+import Pandora.Paradigm.Basis.Cofree (Cofree)
+import Pandora.Paradigm.Junction.Transformer (type (:>:))
+
+class Hollow t where
+	-- | Destructor based on emptiness check
+	hollow :: r -> (Cofree t a -> r ) -> (Cofree :>: t) a -> r
diff --git a/Pandora/Paradigm/Structure/Property/Nonempty.hs b/Pandora/Paradigm/Structure/Property/Nonempty.hs
new file mode 100644
--- /dev/null
+++ b/Pandora/Paradigm/Structure/Property/Nonempty.hs
@@ -0,0 +1,8 @@
+module Pandora.Paradigm.Structure.Property.Nonempty (Nonempty) where
+
+import Pandora.Paradigm.Basis.Cofree (Cofree)
+import Pandora.Paradigm.Junction.Transformer (type (:>:))
+
+-- | Type synonymous for at least one element data structure
+type family Nonempty structure a :: * where
+	Nonempty (Cofree :>: t) a = Cofree t a
diff --git a/Pandora/Paradigm/Structure/Stack.hs b/Pandora/Paradigm/Structure/Stack.hs
deleted file mode 100644
--- a/Pandora/Paradigm/Structure/Stack.hs
+++ /dev/null
@@ -1,27 +0,0 @@
-module Pandora.Paradigm.Structure.Stack (Stack, push, top, pop, empty) where
-
-import Pandora.Core.Functor (type (:.:))
-import Pandora.Core.Morphism ((.), ($))
-import Pandora.Paradigm.Basis.Cofree (Cofree ((:<)), unwrap)
-import Pandora.Paradigm.Basis.Maybe (Maybe (Just, Nothing))
-import Pandora.Paradigm.Junction.Transformer (Y (Y, y), type (:>:))
-import Pandora.Pattern.Functor.Covariant (Covariant ((<$>)))
-import Pandora.Pattern.Functor.Pointable (Pointable (point))
-import Pandora.Pattern.Functor.Extractable (Extractable (extract))
-import Pandora.Pattern.Functor.Alternative (Alternative ((<+>)))
-import Pandora.Pattern.Functor.Bindable (Bindable ((>>=)))
-
-type Stack = (Cofree :>: Maybe)
-
-push :: a -> Stack a -> Stack a
-push x (Y struct) = (Y $ (:<) x . Just <$> struct) <+> point x
-
-top :: Stack a -> Maybe a
-top (Y struct) = extract <$> struct
-
-pop :: Stack a -> Stack a
-pop (Y struct) = Y $ struct >>= unwrap
-
-empty :: r -> (Cofree Maybe a -> r) -> Stack a -> r
-emtpy result _ (Y Nothing) = result
-empty _ f (Y (Just struct)) = f struct
diff --git a/pandora.cabal b/pandora.cabal
--- a/pandora.cabal
+++ b/pandora.cabal
@@ -1,5 +1,5 @@
 name:                pandora
-version:             0.1.1
+version:             0.1.2
 synopsis:            A box of patterns and paradigms
 description:         Humble attempt to define a library for problem solving based on math abstractions.
 homepage:            https://github.com/iokasimov/pandora
@@ -46,6 +46,7 @@
     -- Control flow primitives
     Pandora.Paradigm.Controlflow
     Pandora.Paradigm.Controlflow.Observable
+    Pandora.Paradigm.Controlflow.Pipeline
     -- Tools for datastructures
     Pandora.Paradigm.Inventory
     Pandora.Paradigm.Inventory.Environmental
@@ -54,7 +55,12 @@
     Pandora.Paradigm.Inventory.Storage
     -- Tree-based datastructures
     Pandora.Paradigm.Structure
-    Pandora.Paradigm.Structure.Stack
+    Pandora.Paradigm.Structure.Concrete
+    Pandora.Paradigm.Structure.Property
+    Pandora.Paradigm.Structure.Concrete.Stack
+    Pandora.Paradigm.Structure.Concrete.Graph
+    Pandora.Paradigm.Structure.Property.Hollow
+    Pandora.Paradigm.Structure.Property.Nonempty
     -- Functor typeclassess
     Pandora.Pattern.Functor
     Pandora.Pattern.Functor.Adjoint
@@ -88,6 +94,6 @@
     DataKinds, ConstraintKinds, ExistentialQuantification, QuantifiedConstraints
     FlexibleContexts, FlexibleInstances, KindSignatures, LiberalTypeSynonyms
     MultiParamTypeClasses, NoImplicitPrelude, PackageImports, PolyKinds, RankNTypes
-    TypeApplications, TypeFamilies, TypeOperators
+    ScopedTypeVariables, TypeApplications, TypeFamilies, TypeOperators
   default-language: Haskell2010
   ghc-options: -fno-warn-tabs
