diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Oleg Baev
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Nickolay Kudasov nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/ap-reflect.cabal b/ap-reflect.cabal
new file mode 100644
--- /dev/null
+++ b/ap-reflect.cabal
@@ -0,0 +1,26 @@
+name:                ap-reflect
+version:             0.1.0.0
+synopsis:            Partial evaluation reflection a la simple-reflect.
+-- description:         
+license:             BSD3
+license-file:        LICENSE
+author:              Oleg Baev
+maintainer:          odbaev@yandex.ru
+homepage:            https://github.com/cmc-msu-ai/ap-reflect
+bug-reports:         https://github.com/cmc-msu-ai/ap-reflect/issues
+-- copyright:           
+-- category:            
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  default-language:    Haskell2010
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  exposed-modules:     Debug.Reflect
+  -- other-modules:       
+  build-depends:       base ==4.6.*
+
+Source-Repository head
+  Type:                 git
+  Location:             https://github.com/cmc-msu-ai/ap-reflect.git
diff --git a/src/Debug/Reflect.hs b/src/Debug/Reflect.hs
new file mode 100644
--- /dev/null
+++ b/src/Debug/Reflect.hs
@@ -0,0 +1,129 @@
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE DeriveFunctor #-}
+
+module Debug.Reflect where
+
+import Control.Applicative (Applicative(..), (<$>))
+import Data.List (findIndex, isInfixOf, isPrefixOf)
+import Data.Char (isAlpha)
+
+
+-- | analog of @(->)@
+infixr 5 ~>
+data (~>) a b = Fn String (a -> b) -- ^ name and function itself
+  deriving (Functor)
+
+-- | gets function
+fromFn :: (a ~> b) -> (a -> b)
+fromFn (Fn _ f) = f
+
+instance Show (a ~> b) where
+  show (Fn s _) = s
+
+-- | adds brackets
+parens :: String -> String
+parens s = "(" ++ s ++ ")"
+
+-- | checks whether function is infix
+isInfixFn :: String -> Bool
+isInfixFn = not . any isAlpha
+
+-- | shows function with its argument
+showFn :: String -> String -> String
+showFn f x = if isInfixFn f then x ++ " " ++ f else f ++ " " ++ x
+
+-- | translates function @(a -> b -> c)@ into @(a ~> b ~> c)@
+makeFn2 :: Show a => String -> (a -> b -> c) -> (a ~> b ~> c)
+makeFn2 s f = Fn s $ \x -> Fn (showFn s (show x)) (f x)
+
+-- | makes binary operation
+makeBinOp :: Show a => String -> (a -> b -> c) -> (a ~> b ~> c)
+makeBinOp s f = Fn s' $ \x -> Fn (parens $ showFn s (show x)) (f x)
+  where s' = if isInfixFn s then parens s else s
+
+-- | reflected expression
+data Ap b
+  = Val b
+  | forall a. Show a => Ap (a ~> b) :$ Ap a
+
+-- | checks whether expression is @Val@
+isVal :: Ap a -> Bool
+isVal (Val _) = True
+isVal _ = False
+
+-- | balances brackets
+balanceParens :: String -> String
+balanceParens s = if "<*>" `isInfixOf` s then parens s else s
+
+-- | balances brackets
+parensFr :: String -> String
+parensFr s = if ' ' `elem` s then parens s else s
+
+-- | shows operation application
+showOp :: String -> String -> String -> String
+showOp op f x
+    | isInfixFn op = f ++ " " ++ op ++ " " ++ balanceParens x
+    | otherwise = op ++ " " ++ f ++ " " ++ parensFr x
+
+-- | shows operation application
+showF :: String -> String -> String
+showF f x
+    | "fmap" `isPrefixOf` f = f ++ " " ++ parensFr x
+    | otherwise = f ++ " " ++ balanceParens x
+
+instance Show a => Show (Ap a) where
+  show (Val x) = show x
+  show (op :$ f :$ x) = showOp (show op) (show f) (show x)
+  show (f :$ x) = showF (show f) (show x)
+
+-- | analog of @fmap@ using @(~>)@
+fmap' :: Functor f => (a ~> b) ~> f a ~> f b
+fmap' = makeFn2 "<$>" (fmap . fromFn)
+
+-- | analog of @pure@ using @(~>)@
+pure' :: Applicative f => a ~> f a
+pure' = Fn "pure" pure
+
+-- | analog of @\<*>@ using @(~>)@
+ap' :: (Show (f (a ~> b)), Applicative f) => f (a ~> b) ~> f a ~> f b
+ap' = Fn "<*>" $ \f -> Fn (show f ++ " <*>") $ \x -> fromFn <$> f <*> x
+
+-- | analog of  @\<$>@
+infix 6 -$-
+(-$-) :: (Show (f a), Functor f) => (a ~> b) -> f a -> Ap (f b)
+f -$- x = Val fmap' :$ Val f :$ Val x
+
+-- | analog of @\<*>@
+infixl 5 -*-
+(-*-) :: (Show (f (a ~> b)), Show (f a), Applicative f) => Ap (f (a ~> b)) -> f a -> Ap (f b)
+f -*- x = Val ap' :$ f :$ Val x
+
+-- | analog of @pure@
+pure'' :: (Show a, Applicative f) => a -> Ap (f a)
+pure'' x = Val pure' :$ Val x
+
+-- | analog of @fmap@
+fmap'' :: (Show (f a), Functor f) => (a ~> b) -> f a -> Ap (f b)
+fmap'' f x = Val (makeFn2 "fmap" (fmap . fromFn)) :$ Val f :$ Val x
+
+-- | reduces an expression
+reduce'' :: Ap a -> Ap a
+reduce'' (Val (Fn _ f) :$ Val x) = Val (f x)
+reduce'' (Val f :$ x) = Val f :$ reduce'' x
+reduce'' (f :$ x) = reduce'' f :$ x
+reduce'' v = v
+
+-- | reduces (evaluates) an expression once
+reduce' :: Show a => Ap a -> Ap a
+reduce' x
+    | isVal x = x
+    | otherwise = head $ filter (\x' -> show x' /= show x) xs
+    where xs = iterate reduce'' x
+
+-- | gets all reduction steps when evaluating an expression
+reductions :: Show a => Ap a -> [Ap a]
+reductions x = take (n + 1) xs
+  where
+    Just n = findIndex isVal xs
+    xs = iterate reduce' x
