diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+The MIT License (MIT)
+Copyright (c) 2016-2017 Tao He
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/mxnet-nnvm.cabal b/mxnet-nnvm.cabal
new file mode 100644
--- /dev/null
+++ b/mxnet-nnvm.cabal
@@ -0,0 +1,27 @@
+name:                       mxnet-nnvm
+version:                    0.1.0.0
+synopsis:                   NNVM interface in Haskell.
+description:                NNVM interface in Haskell via CFFI.
+homepage:                   http://github.com/sighingnow/mxnet-haskell#readme
+license:                    MIT
+license-file:               LICENSE
+author:                     Tao He
+maintainer:                 sighingnow@gmail.com
+copyright:                  Copyright: (c) 2016-2017 Tao He
+category:                   Machine Learning
+build-type:                 Simple
+cabal-version:              >= 1.10
+
+Library
+    exposed-modules:
+        MXNet.NNVM.Base
+    other-modules:
+        MXNet.NNVM.Internal.Types.Raw
+        MXNet.NNVM.Base.Internal.Raw
+    hs-source-dirs:         src
+    build-tools:            c2hs
+    ghc-options:            -Wall
+    default-language:       Haskell2010
+    build-depends:          base >= 4.7 && < 5.0
+                          , c2hs-extra >= 0.1
+    extra-libraries:        mxnet
diff --git a/src/MXNet/NNVM/Base.hs b/src/MXNet/NNVM/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/MXNet/NNVM/Base.hs
@@ -0,0 +1,49 @@
+-----------------------------------------------------------
+-- |
+-- module:                      MXNet.NNVM.Base
+-- copyright:                   (c) 2016 Tao He
+-- license:                     MIT
+-- maintainer:                  sighingnow@gmail.com
+--
+-- Interfaces in core module of NNVM.
+--
+module MXNet.NNVM.Base (
+      -- * Re-export data type definitions
+      NNUInt
+    , OpHandle
+    , SymbolHandle
+    , GraphHandle
+      -- * Re-export functions.
+    , nnAPISetLastError
+    , nnGetLastError
+    , nnListAllOpNames
+    , nnGetOpHandle
+    , nnListUniqueOps
+    , nnGetOpInfo
+    , nnSymbolCreateAtomicSymbol
+    , nnSymbolCreateVariable
+    , nnSymbolCreateGroup
+    , nnAddControlDeps
+    , nnSymbolFree
+    , nnSymbolCopy
+    , nnSymbolPrint
+    , nnSymbolGetAttr
+    , nnSymbolSetAttrs
+    , nnSymbolListAttrs
+    , nnSymbolListInputVariables
+    , nnSymbolListInputNames
+    , nnSymbolListOutputNames
+    , nnSymbolGetInternals
+    , nnSymbolGetOutput
+    , nnSymbolCompose
+    , nnGraphCreate
+    , nnGraphFree
+    , nnGraphGetSymbol
+    , nnGraphSetJSONAttr
+    , nnGraphGetJSONAttr
+    , nnGraphSetNodeEntryListAttr_
+    , nnGraphApplyPasses
+    ) where
+
+import MXNet.NNVM.Internal.Types.Raw
+import MXNet.NNVM.Base.Internal.Raw
diff --git a/src/MXNet/NNVM/Base/Internal/Raw.chs b/src/MXNet/NNVM/Base/Internal/Raw.chs
new file mode 100644
--- /dev/null
+++ b/src/MXNet/NNVM/Base/Internal/Raw.chs
@@ -0,0 +1,248 @@
+-----------------------------------------------------------
+-- |
+-- module:                      MXNet.NNVM.Base.Internal.Raw
+-- copyright:                   (c) 2016 Tao He
+-- license:                     MIT
+-- maintainer:                  sighingnow@gmail.com
+--
+-- Direct C FFI bindings for <mxnet/c_api.h>.
+--
+#if __GLASGOW_HASKELL__ >= 709
+{-# LANGUAGE Safe #-}
+#elif __GLASGOW_HASKELL__ >= 701
+{-# LANGUAGE Trustworthy #-}
+#endif
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module MXNet.NNVM.Base.Internal.Raw where
+
+import Foreign.C.String
+import Foreign.C.Types
+import Foreign.Marshal.Alloc
+import Foreign.Marshal.Array
+import Foreign.Marshal.Utils ( with )
+import Foreign.Ptr
+import Foreign.Storable
+
+import C2HS.C.Extra.Marshal
+
+{#import MXNet.NNVM.Internal.Types.Raw #}
+
+#include <nnvm/c_api.h>
+
+{#fun NNAPISetLastError as nnAPISetLastError
+    { `String'
+    } -> `()' #}
+
+{#fun NNGetLastError as nnGetLastError
+    {
+    } -> `String' #}
+
+{#fun NNListAllOpNames as nnListAllOpNamesImpl
+    { alloca- `NNUInt' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    } -> `Int' #}
+
+nnListAllOpNames :: IO (Int, NNUInt, [String])
+nnListAllOpNames = do
+    (res, n, p) <- nnListAllOpNamesImpl
+    ss <- peekStringArray n p
+    return (res, n, ss)
+
+{#fun NNGetOpHandle as nnGetOpHandle
+    { `String'
+    , alloca- `OpHandle' peek*
+    } -> `Int' #}
+
+{#fun NNListUniqueOps as nnListUniqueOpsImpl
+    { alloca- `NNUInt' peek*
+    , alloca- `Ptr OpHandle' peek*
+    } -> `Int' #}
+
+nnListUniqueOps :: IO (Int, NNUInt, [OpHandle])
+nnListUniqueOps = do
+    (res, n, p) <- nnListUniqueOpsImpl
+    ops <- peekArray (fromIntegral n) p
+    return (res, n, ops)
+
+{#fun NNGetOpInfo as nnGetOpInfoImpl
+    { id `OpHandle'
+    , alloca- `String' peekString* -- ^ return a name (string).
+    , alloca- `String' peekString* -- ^ return description (string).
+    , alloca- `NNUInt' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    , alloca- `String' peekString*
+    } -> `Int' #}
+
+nnGetOpInfo :: OpHandle
+            -> IO (Int, String, String, NNUInt, [String], [String], [String], String)
+nnGetOpInfo handle = do
+    (res, name, desc, argc, pargv, pargt, pargdesc, rettype) <- nnGetOpInfoImpl handle
+    argv <- peekStringArray argc pargv
+    argt <- peekStringArray argc pargt
+    argdesc <- peekStringArray argc pargdesc
+    return (res, name, desc, argc, argv, argt, argdesc, rettype)
+
+{#fun NNSymbolCreateAtomicSymbol as nnSymbolCreateAtomicSymbol
+    { id `OpHandle'
+    , id `NNUInt'
+    , withStringArray* `[String]'
+    , withStringArray* `[String]'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNSymbolCreateVariable as nnSymbolCreateVariable
+    { `String'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNSymbolCreateGroup as nnSymbolCreateGroup
+    { id `NNUInt'
+    , withArray* `[SymbolHandle]'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNAddControlDeps as nnAddControlDeps
+    { id `SymbolHandle' -- ^ The symbol to add dependency edges on.
+    , id `SymbolHandle' -- ^ The source handles.
+    } -> `Int' #}
+
+{#fun NNSymbolFree as nnSymbolFree
+    { id `SymbolHandle'
+    } -> `Int' #}
+
+{#fun NNSymbolCopy as nnSymbolCopy
+    { id `SymbolHandle'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNSymbolPrint as nnSymbolPrint
+    { id `SymbolHandle'
+    , alloca- `String' peekString*
+    } -> `Int' #}
+
+{#fun NNSymbolGetAttr as nnSymbolGetAttr
+    { id `SymbolHandle'             -- ^ symbol handle
+    , `String'                      -- ^ key
+    , alloca- `String' peekString*  -- ^ result value
+    , alloca- `Int' peekIntegral*   -- ^ if success, 0 when success, -1 when failure happens.
+    } -> `Int' #}
+
+{#fun NNSymbolSetAttrs as nnSymbolSetAttrs
+    { id `SymbolHandle'
+    , id `NNUInt'
+    , withStringArray* `[String]' -- ^ attribute keys
+    , withStringArray* `[String]' -- ^ attribute values
+    } -> `Int' #}
+
+{#fun NNSymbolListAttrs as nnSymbolListAttrsImpl
+    { id `SymbolHandle'
+    , `Int'                           -- ^ 0 for recursive, 1 for shallow
+    , alloca- `NNUInt' peek*          -- ^ out size
+    , alloca- `Ptr (Ptr CChar)' peek* -- ^ out attributes
+    } -> `Int' #}
+
+nnSymbolListAttrs :: SymbolHandle -> Int -> IO (Int, NNUInt, [String])
+nnSymbolListAttrs sym recursive = do
+    (res, n, p) <- nnSymbolListAttrsImpl sym recursive
+    ss <- peekStringArray n p
+    return (res, n, ss)
+
+{#fun NNSymbolListInputVariables as nnSymbolListInputVariablesImpl
+    { id `SymbolHandle'
+    , `Int'
+    , alloca- `NNUInt' peek*
+    , alloca- `Ptr SymbolHandle' peek*
+    } -> `Int' #}
+
+nnSymbolListInputVariables :: SymbolHandle -> Int -> IO (Int, NNUInt, [SymbolHandle])
+nnSymbolListInputVariables sym opt = do
+    (res, n, p) <- nnSymbolListInputVariablesImpl sym opt
+    vs <- peekArray (fromIntegral n) p
+    return (res, n, vs)
+
+{#fun NNSymbolListInputNames as nnSymbolListInputNamesImpl
+    { id `SymbolHandle'
+    , `Int'
+    , alloca- `NNUInt' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    } -> `Int' #}
+
+nnSymbolListInputNames :: SymbolHandle -> Int -> IO (Int, NNUInt, [String])
+nnSymbolListInputNames sym opt = do
+    (res, n, p) <- nnSymbolListInputNamesImpl sym opt
+    ss <- peekStringArray n p
+    return (res, n, ss)
+
+{#fun NNSymbolListOutputNames as nnSymbolListOutputNamesImpl
+    { id `SymbolHandle'
+    , alloca- `NNUInt' peek*
+    , alloca- `Ptr (Ptr CChar)' peek*
+    } -> `Int' #}
+
+nnSymbolListOutputNames :: SymbolHandle -> IO (Int, NNUInt, [String])
+nnSymbolListOutputNames sym = do
+    (res, n, p) <- nnSymbolListOutputNamesImpl sym
+    ss <- peekStringArray n p
+    return (res, n, ss)
+
+{#fun NNSymbolGetInternals as nnSymbolGetInternals
+    { id `SymbolHandle'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNSymbolGetOutput as nnSymbolGetOutput
+    { id `SymbolHandle'
+    , id `NNUInt'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNSymbolCompose as nnSymbolCompose
+    { id `SymbolHandle'
+    , `String'
+    , id `NNUInt'
+    , withStringArray* `[String]'
+    , alloca- `SymbolHandle' peek*
+    } -> `Int' #}
+
+{#fun NNGraphCreate as nnGraphCreate
+    { id `SymbolHandle'
+    , alloca- `GraphHandle' peek*
+    } -> `Int' #}
+
+{#fun NNGraphFree as nnGraphFree
+    { id `GraphHandle'
+    } -> `Int' #}
+
+{#fun NNGraphGetSymbol as nnGraphGetSymbol
+    { id `GraphHandle'             -- ^ the graph handle.
+    , alloca- `SymbolHandle' peek* -- ^ the corresponding symbol.
+    } -> `Int' #}
+
+{#fun NNGraphSetJSONAttr as nnGraphSetJSONAttr
+    { id `GraphHandle'
+    , `String'
+    , `String'
+    } -> `Int' #}
+
+{#fun NNGraphGetJSONAttr as nnGraphGetJSONAttr
+    { id `SymbolHandle'
+    , `String'
+    , alloca- `String' peekString*
+    , alloca- `Int' peekIntegral* -- ^ if success.
+    } -> `Int' #}
+
+{#fun NNGraphSetNodeEntryListAttr_ as nnGraphSetNodeEntryListAttr_
+    { id `GraphHandle'
+    , `String'
+    , `SymbolHandle'
+    } -> `Int' #}
+
+{#fun NNGraphApplyPasses as nnGraphApplyPasses
+    { id `GraphHandle'
+    , id `NNUInt'
+    , withStringArray* `[String]'
+    , alloca- `GraphHandle' peek*
+    } -> `Int' #}
diff --git a/src/MXNet/NNVM/Internal/Types/Raw.chs b/src/MXNet/NNVM/Internal/Types/Raw.chs
new file mode 100644
--- /dev/null
+++ b/src/MXNet/NNVM/Internal/Types/Raw.chs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------
+-- |
+-- module:                      MXNet.NNVM.Internal.Types.Raw
+-- copyright:                   (c) 2016 Tao He
+-- license:                     MIT
+-- maintainer:                  sighingnow@gmail.com
+--
+-- Collect data type defintions of NNVM into a single raw binding module to
+-- avoid redefinitions.
+--
+#if __GLASGOW_HASKELL__ >= 709
+{-# LANGUAGE Safe #-}
+#elif __GLASGOW_HASKELL__ >= 701
+{-# LANGUAGE Trustworthy #-}
+#endif
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module MXNet.NNVM.Internal.Types.Raw where
+
+import Foreign.C.Types
+import Foreign.Marshal.Alloc
+import Foreign.Marshal.Array
+import Foreign.Marshal.Utils ( with )
+import Foreign.Ptr
+import Foreign.Storable
+
+#include <nnvm/c_api.h>
+
+{---------------------------------------------------------------------
+- <nnvm/c_api.h>
+---------------------------------------------------------------------}
+
+-- | MXUint type alias.
+type NNUInt = CUInt
+
+-- | Handle to a function that takes param and creates symbol.
+{#pointer OpHandle newtype #}
+
+instance Storable OpHandle where
+    sizeOf (OpHandle t) = sizeOf t
+    alignment (OpHandle t) = alignment t
+    peek p = fmap OpHandle (peek (castPtr p))
+    poke p (OpHandle t) = poke (castPtr p) t
+
+-- | Handle to a symbol that can be bind as operator.
+{#pointer SymbolHandle newtype #}
+
+instance Storable SymbolHandle where
+    sizeOf (SymbolHandle t) = sizeOf t
+    alignment (SymbolHandle t) = alignment t
+    peek p = fmap SymbolHandle (peek (castPtr p))
+    poke p (SymbolHandle t) = poke (castPtr p) t
+
+-- | Handle to Graph.
+{#pointer GraphHandle newtype #}
+
+instance Storable GraphHandle where
+    sizeOf (GraphHandle t) = sizeOf t
+    alignment (GraphHandle t) = alignment t
+    peek p = fmap GraphHandle (peek (castPtr p))
+    poke p (GraphHandle t) = poke (castPtr p) t
