diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for oeis
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Okkey (c) 2018
+
+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 Okkey 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,65 @@
+# oeis2
+
+Haskell interface for [Online Encyclopedia of Integer Sequences](https://oeis.org/); homage to [oeis](http://hackage.haskell.org/package/oeis).
+
+## Difference from  [oeis](http://hackage.haskell.org/package/oeis)
+
+- Source data of OEIS.  
+  : [oeis](http://hackage.haskell.org/package/oeis) use `fmt=text`, but this library use `fmt=json`.
+- Possible to get all search results.
+- Search functions from ID or sub-sequence are merged.
+- Possibele to search from **other** than ID or sub-sequence.
+- Support for HTTPS.
+
+## Usage
+
+Add import statement.
+
+```haskell
+import Math.OEIS
+```
+
+- Get all search results from sub-sequence
+
+    - If `n == 0`, you get all search results.
+
+        ```haskell
+        ghci>searchSeq (SubSeq [1,2,3,4]) 0
+        [OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,...
+        ghci>length it
+        53
+        ```
+
+    - Otherwise, you get first `n` search results.
+
+        ```haskell
+        ghci>searchSeq (SubSeq [1,2,3,4]) 17
+        [OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,8,9,
+        ghci>length it
+        17
+        ```
+
+- Get first few terms from sub-sequence
+
+    ```haskell
+    ghci>getSeqData (SubSeq [1,2,2,3,3,3,4,4,4,4])
+    Just [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,7,...
+    ```
+
+-  Get Mathematica function from sub-sequence
+
+    ```haskell
+    ghci>mathematica <$> lookupSeq (SubSeq [1,2,2,3,3,3,4,4,4,4])
+    Just ["a[1] = 1; a[n_] := a[n] = a[n - a[n - 1]] + 1 (* _Branko Curgus_, May 12 2009 *)","Table[n, {n, 13}, {n}] // Flatten (* _Robert G. Wilson v_, May 11 2010 *)"]
+    ```
+
+- If no search result
+
+    ```haskell
+    ghci>lookupSeq (ID "1145141919893")
+    Nothing
+    ```
+
+## ToDo
+
+-  Could use other functions of the searching system written in [here](https://oeis.org/hints.html).
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/oeis2.cabal b/oeis2.cabal
new file mode 100644
--- /dev/null
+++ b/oeis2.cabal
@@ -0,0 +1,69 @@
+-- This file has been generated from package.yaml by hpack version 0.28.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: dfea261a0cd8b7a597f5717df1093a6c7c1acf8250c469966c4c360b62652f15
+
+name:           oeis2
+version:        0.1.0
+synopsis:       Interface for Online Encyclopedia of Integer Sequences (OEIS).
+description:    Please see the README on GitHub at <https://github.com/23_prime/oeis2#readme>
+category:       Math
+homepage:       https://github.com/23_prime/oeis2#readme
+bug-reports:    https://github.com/23_prime/oeis2/issues
+author:         okkey
+maintainer:     a23b23c23d23e@gmail.com
+copyright:      2018 okkey
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+extra-source-files:
+    ChangeLog.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/23_prime/oeis2
+
+library
+  exposed-modules:
+      Math.OEIS
+      Math.OEIS.Internal
+      Math.OEIS.Types
+  other-modules:
+      Paths_oeis2
+  hs-source-dirs:
+      src
+  build-depends:
+      aeson >=1.3 && <1.5
+    , base >=4.7 && <5
+    , containers >=0.5 && <0.7
+    , http-conduit >=2.3 && <2.4
+    , lens >=4.16 && <4.18
+    , lens-aeson >=1.0 && <1.1
+    , text >=1.2 && <1.3
+    , vector >=0.12 && <0.13
+  default-language: Haskell2010
+
+test-suite oeis2-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_oeis2
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      QuickCheck
+    , aeson >=1.3 && <1.5
+    , base >=4.7 && <5
+    , containers >=0.5 && <0.7
+    , hspec
+    , http-conduit >=2.3 && <2.4
+    , lens >=4.16 && <4.18
+    , lens-aeson >=1.0 && <1.1
+    , oeis2
+    , text >=1.2 && <1.3
+    , vector >=0.12 && <0.13
+  default-language: Haskell2010
diff --git a/src/Math/OEIS.hs b/src/Math/OEIS.hs
new file mode 100644
--- /dev/null
+++ b/src/Math/OEIS.hs
@@ -0,0 +1,118 @@
+{-# LANGUAGE OverloadedLists #-}
+
+module Math.OEIS (
+  -- * Types
+  SeqData,
+  SearchStatus(..),
+--  Language(..),
+  Keyword(..),
+  OEISSeq(..),
+
+  -- * Functions
+  searchSeq',  searchSeq,
+  lookupSeq',  lookupSeq,
+  getSeqData', getSeqData,
+  extendSeq',  extendSeq
+  ) where
+
+import           Data.List
+import           Data.Maybe         (fromMaybe, listToMaybe)
+import qualified Data.Vector        as V
+import           System.IO.Unsafe   (unsafePerformIO)
+
+import           Math.OEIS.Internal
+import           Math.OEIS.Types
+
+
+-- | Get all search results on OEIS
+--
+-- e.g.
+--
+-- > ghci>searchSeq (ID "A000027") 0
+-- > [OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,...
+--
+-- > ghci>searchSeq (SubSeq [1,2,3,4]) 0
+-- > [OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,...
+-- > ghci>length it
+-- > 53
+-- > ghci>searchSeq (SubSeq [1,2,3,4]) 17
+-- > [OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,8,9,
+-- > ghci>length it
+-- > 17
+--
+-- > ghci>searchSeq (SubSeq [1,1,4,5,1,4,1,9,1,9,8,9,3]) 0
+-- > []
+searchSeq' :: SearchStatus -> Int -> IO (V.Vector OEISSeq)
+searchSeq' ss bound = do
+  results' <- getResults ss 0 bound []
+  let seqs
+        | V.null results' = []
+        | otherwise       = parseOEIS <$> results'
+  return seqs
+
+searchSeq :: SearchStatus -> Int -> V.Vector OEISSeq
+searchSeq ss = unsafePerformIO . searchSeq' ss
+
+
+-- | Look up a sequence on OEIS.
+--
+-- e.g.
+--
+-- > ghci>lookupSeq (ID "A000027")
+-- > Just (OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,...
+--
+-- > ghci>lookupSeq (SubSeq [1,2,3,4])
+-- > Just (OEIS {number = "A000027", ids = ["M0472","N0173"], seqData = [1,2,3,4,5,6,7,...
+lookupSeq :: SearchStatus -> Maybe OEISSeq
+lookupSeq = unsafePerformIO . lookupSeq'
+
+-- | lookupSeq in IO
+lookupSeq' :: SearchStatus -> IO (Maybe OEISSeq)
+lookupSeq' ss = do
+  result <- getResult ss 0
+  return $ case result of
+             Just result' -> Just $ parseOEIS result'
+             _            -> Nothing
+
+
+-- | Get sub-sequence on OEIS.
+--
+-- e.g.
+--
+-- > ghci>getSeqData (ID "A000027")
+-- > Just [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77]
+--
+-- > ghci>getSeqData (SubSeq [1,2,3,4])
+-- > Just [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77]
+--
+getSeqData :: SearchStatus -> Maybe SeqData
+getSeqData = unsafePerformIO . getSeqData'
+
+-- | getSeqData in IO
+getSeqData' :: SearchStatus -> IO (Maybe SeqData)
+getSeqData' = ((seqData <$>) <$>) . lookupSeq'
+
+
+-- | Extend from sub-sequence.
+--
+-- e.g.
+--
+-- > ghci>extendSeq [1,2,3,4]
+-- > [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77]
+--
+-- > ghci> extendSeq [1,3,2,5,6,1,6]
+-- > [1,3,2,5,6,1,6]
+extendSeq :: SeqData -> SeqData
+extendSeq = unsafePerformIO . extendSeq'
+
+-- | extendSeq in IO
+extendSeq' :: [Integer] -> IO [Integer]
+extendSeq' [] = return []
+extendSeq' sd = do
+  oeis <- lookupSeq' (SubSeq sd)
+  return $ case oeis of
+    Just s -> extend sd (seqData s)
+    _      -> sd
+  where
+    extend :: SeqData -> SeqData -> SeqData
+    extend sd ext = fromMaybe sd . listToMaybe . filter (sd `isPrefixOf`) $ tails ext
diff --git a/src/Math/OEIS/Internal.hs b/src/Math/OEIS/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Math/OEIS/Internal.hs
@@ -0,0 +1,220 @@
+{-# LANGUAGE OverloadedLists   #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Math.OEIS.Internal where
+
+import           Control.Lens        ((^?), (^?!))
+import           Control.Monad       (when)
+import           Data.Aeson.Lens
+import           Data.Aeson.Types
+import           Data.Char
+import           Data.List
+import           Data.Maybe          (fromJust, fromMaybe, isNothing)
+import qualified Data.Text           as T
+import qualified Data.Text.Encoding  as T
+import qualified Data.Text.IO        as T
+import qualified Data.Vector         as V
+import           Network.HTTP.Simple (getResponseBody, httpBS, parseRequest)
+import           System.IO.Unsafe    (unsafePerformIO)
+
+import           Math.OEIS.Types
+
+
+---------------
+-- JSON Keys --
+---------------
+intKeys = [
+  "number", "offset", "references", "revision"
+  ]
+textKeys = [
+  "id", "data", "name", "keyword", "author", "time", "created"
+  ]
+textsKeys = [
+  "comment", "reference", "link", "formula", "example", "maple", "mathematica",
+  "program", "xref", "ext"
+  ]
+keys = intKeys ++ textKeys ++ textsKeys :: Texts
+
+
+----------------
+-- Text utils --
+----------------
+(+.+) = T.append
+(.+)  = T.cons
+(+.)  = T.snoc
+
+
+----------------------
+-- Get JSON of OEIS --
+----------------------
+showSeqData :: SeqData -> T.Text
+showSeqData = T.pack . tail . init . show
+
+readSeqData :: String -> SeqData
+readSeqData str = case reads ("[" ++ str ++ "]") of
+                    [(sd, "")] -> sd
+                    _          -> []
+
+baseSearchURI :: T.Text
+baseSearchURI = "https://oeis.org/search?fmt=json&q="
+
+addPrefix :: SearchStatus -> T.Text
+addPrefix (SubSeq ints) = "seq:" +.+ showSeqData ints
+addPrefix ss            = let (cst, txt) = T.breakOn " " $ T.pack $ show ss
+                              pref       = T.toLower cst +.+ ":"
+                              txt'       = T.init $ T.tail $ T.strip txt
+                          in pref +.+ txt'
+
+searchURI :: SearchStatus -> T.Text
+searchURI ss = baseSearchURI +.+ addPrefix ss
+
+openURL :: T.Text -> IO T.Text
+openURL x = T.decodeUtf8 . getResponseBody <$> (httpBS =<< parseRequest (T.unpack x))
+
+getJSON :: SearchStatus -> Int -> IO T.Text
+getJSON (Others txt) _ = return txt -- for test
+getJSON ss n           = openURL $ searchURI ss +.+ "&start=" +.+ T.pack (show n)
+
+
+----------------
+-- Parse JSON --
+----------------
+-- Get all search results --
+getResults :: SearchStatus -> Int -> Int -> V.Vector Value -> IO (V.Vector Value)
+getResults ss start bound vs = do
+  when (bound < 0) $ fail "Upper-bound number of search results mast be non-negative."
+  jsn <- getJSON ss start
+  let results' = jsn ^? key "results" . _Array
+      results = case results' of
+        Nothing  -> return []
+        Just vs' ->
+          let len    = length vs'
+              start' = start + 10
+              diff   = case bound of
+                         0 -> len
+                         _ -> bound - start
+          in case ss of
+               ID _     -> return vs'
+               Others _ -> return vs'
+               _ ->
+                if bound /= 0 && diff <= 10 || len /= 10 then
+                  return $ vs V.++ V.take diff vs'
+                else
+                  getResults ss start' bound $ vs V.++ vs'
+  results
+
+-- Get nth search result --
+getResult :: SearchStatus -> Int -> IO (Maybe Value)
+getResult ss n = do
+  results <- getResults ss 0 (n + 1) []
+  let result = results V.!? n
+  return result
+
+-- Get each data in result --
+getData :: Value -> T.Text -> (T.Text, Maybe OEISData)
+getData result k
+  | k `elem` intKeys
+  = let d = result ^? key k ._Integer
+    in case d of
+      Nothing -> (k, Nothing)
+      _       ->
+        case k of
+          "number" -> let d'  = T.pack $ show $ fromJust d
+                          len = T.length d'
+                      in (k, Just $ TXT $ 'A' .+ T.replicate (6 - len) "0" +.+ d')
+          _        -> (k, INT <$> d)
+  | k `elem` textKeys
+  = let d = result ^? key k ._String
+    in case d of
+      Nothing -> (k, Nothing)
+      _       ->
+        case k of
+          "keyword" -> (k, KEYS . map readKeyword . T.splitOn "," <$> d)
+          "data"    -> let d' = T.unpack $ '[' .+ fromJust d +. ']'
+                       in (k, Just $ SEQ (read d' :: SeqData))
+          "id"      -> (k, TXTS . T.splitOn " " <$> d)
+          _         -> (k, TXT <$> d)
+  | k `elem` textsKeys
+  = let ds  = result ^? key k . _Array
+    in case ds of
+         Nothing -> (k, Nothing)
+         _       -> let ts  = (\i -> result ^?! key k . nth i . _String) <$> [0..(len - 1)]
+                        len = fromJust $ length <$> ds
+                    in case k of
+                         "program" -> let prgs = parsePrograms emptyProgram [] ts
+                                      in (k, Just $ PRGS prgs)
+                         _         -> (k, Just $ TXTS ts)
+  | otherwise = (k, Nothing)
+
+resultLen :: SearchStatus -> IO (Maybe Int)
+resultLen ss = do
+  jsn <- getJSON ss 0
+  return $ fromInteger <$> jsn ^? key "count" . _Integer
+
+emptyOEIS :: OEISSeq
+emptyOEIS = OEIS "" [] [] "" [] [] [] [] [] [] [] [] [] [] 0 "" [] 0 0 "" ""
+
+addElement :: OEISSeq -> (T.Text, Maybe OEISData) -> OEISSeq
+addElement seq (k, Just (TXT t))
+  = case k of
+      "number"  -> seq {number = t}
+      "name"    -> seq {name = t}
+      "author"  -> seq {author = t}
+      "time"    -> seq {time = t}
+      "created" -> seq {created = t}
+      _         -> seq
+addElement seq (k, Just (TXTS ts))
+  = case k of
+      "id"          -> seq {ids = ts}
+      "comment"     -> seq {comment = ts}
+      "reference"   -> seq {reference = ts}
+      "link"        -> seq {link = ts}
+      "formula"     -> seq {formula = ts}
+      "example"     -> seq {example = ts}
+      "maple"       -> seq {maple = ts}
+      "mathematica" -> seq {mathematica = ts}
+      "xref"        -> seq {xref = ts}
+      "ext"         -> seq {ext = ts}
+      _             -> seq
+addElement seq (k, Just (INT n))
+  = case k of
+      "offset"     -> seq {offset = n}
+      "references" -> seq {references = n}
+      "revision"   -> seq {revision = n}
+      _            -> seq
+addElement seq ("data"   , Just (SEQ s))   = seq {seqData = s}
+addElement seq ("keyword", Just (KEYS ks)) = seq {keyword = ks}
+addElement seq ("program", Just (PRGS ps)) = seq {program = ps}
+addElement seq (_, _) = seq
+
+parseOEIS :: Value -> OEISSeq
+parseOEIS result = foldl' addElement emptyOEIS $ map (getData result) keys
+
+
+-- Parse Keyword --
+readKeyword :: T.Text -> Keyword
+readKeyword txt =
+  let str = T.unpack $ capitalize txt
+  in case reads str of
+       [(kw, "")] -> kw
+       _          -> Other
+
+capitalize :: T.Text -> T.Text
+capitalize "" = ""
+capitalize cs = toUpper (T.head cs) .+ T.map toLower (T.tail cs)
+
+
+-- Parse Program --
+emptyProgram = ("", []) :: Program
+
+parsePrograms :: Program -> [Program] -> [T.Text] -> [Program]
+parsePrograms _ prgs [] = prgs
+parsePrograms (lang0, funcs) prgs (t : ts)
+  | T.head t == '(' = let prgs' = prgs ++ [(lang, [func])]
+                      in parsePrograms (lang, [func]) prgs' ts
+  | otherwise       = let prgs' = init prgs ++ [(lang0, funcs ++ [t])]
+                      in parsePrograms (lang0, funcs ++ [t]) prgs' ts
+  where
+    (lang', func') = T.breakOn ")" t
+    lang           = T.tail lang'
+    func           = T.strip $ T.tail func'
diff --git a/src/Math/OEIS/Types.hs b/src/Math/OEIS/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Math/OEIS/Types.hs
@@ -0,0 +1,78 @@
+module Math.OEIS.Types where
+
+import qualified Data.Text as T
+
+type SeqData = [Integer]
+type Texts = [T.Text]
+
+-- Prefixes
+{-
+id:                     ref:                    program:
+seq:                    link:                   xref:
+signed:                 formula:                keyword:
+name:                   example:                author:
+offset:                 maple:                  extension:
+comment:                mathematica:
+-}
+data SearchStatus = ID T.Text
+                  | SubSeq SeqData
+                  | Signed T.Text
+                  | Name T.Text
+                  | Comment T.Text
+                  | Ref T.Text
+                  | Link T.Text
+                  | Formla T.Text
+                  | Example T.Text
+                  | Maple T.Text
+                  | Mathematica T.Text
+                  | Offset T.Text
+                  | Program T.Text
+                  | XRef T.Text
+                  | KeyWord T.Text
+                  | Author T.Text
+                  | Extension T.Text
+                  | Others T.Text
+  deriving (Show, Eq)
+
+--data Language = Haskell | PARI | L T.Text deriving (Show, Eq)
+type Language = T.Text
+type Program = (Language, [T.Text])
+
+data Keyword = Base | Bref | Changed | Cofr | Cons | Core | Dead | Dumb | Dupe |
+               Easy | Eigen | Fini | Frac | Full | Hard | More | Mult |
+               New | Nice | Nonn | Obsc | Sign | Tabf | Tabl | Uned |
+               Unkn | Walk | Word | Look | Other
+  deriving (Eq, Show, Read)
+
+data OEISData = INT Integer
+              | SEQ SeqData
+              | TXT T.Text
+              | TXTS Texts
+              | KEYS [Keyword]
+              | PRGS [Program]
+  deriving (Show)
+
+data OEISSeq
+  = OEIS { number      :: T.Text,
+           ids         :: Texts,
+           seqData     :: SeqData,
+           name        :: T.Text,
+           comment     :: Texts,
+           reference   :: Texts,
+           link        :: Texts,
+           formula     :: Texts,
+           example     :: Texts,
+           maple       :: Texts,
+           mathematica :: Texts,
+           program     :: [Program],
+           xref        :: Texts,
+           keyword     :: [Keyword],
+           offset      :: Integer,
+           author      :: T.Text,
+           ext         :: Texts,
+           references  :: Integer,
+           revision    :: Integer,
+           time        :: T.Text,
+           created     :: T.Text
+         }
+  deriving (Show, Eq, Read)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import           Data.Aeson.Lens
+import           Data.Aeson.Types
+import           Data.List
+import           Data.Maybe            (fromJust)
+import qualified Data.Text             as T
+import qualified Data.Text.IO          as T
+import qualified Data.Vector           as V
+import           System.IO
+import           System.IO.Unsafe      (unsafePerformIO)
+import           Test.Hspec
+import           Test.Hspec.QuickCheck
+import           Test.QuickCheck.Gen
+
+import           Math.OEIS
+import           Math.OEIS.Internal
+
+
+main :: IO ()
+main = do
+  withFile "./test/docs/test.json" ReadMode $ \handle1 ->
+    withFile "./test/docs/result.txt" ReadMode $ \handle2 -> do
+      testJSON    <- T.hGetContents handle1
+      testResult' <- hGetContents handle2
+      let testResult = read testResult' :: V.Vector OEISSeq
+      hspec $ specSearchSeq testJSON testResult
+  hspec specLookupSeq
+  hspec specGetSeqData
+  hspec specExtendSeq
+
+specSearchSeq :: T.Text -> V.Vector OEISSeq -> Spec
+specSearchSeq jsn seq = describe "Test for searchSeq" $ do
+  it "Number of all search results" $
+    length (searchSeq (SubSeq [1,2,2,3,3,3,4,4,4,4]) 0) `shouldBe`
+    fromJust (unsafePerformIO $ resultLen (SubSeq [1,2,2,3,3,3,4,4,4,4]))
+  it "Get some of search results" $
+    searchSeq (Others jsn) 10 `shouldBe` seq
+  it "No search results" $
+    searchSeq (SubSeq [1, 2, 3, 6, 11, 23, 47, 106, 237]) 0 `shouldBe` V.empty
+
+specLookupSeq :: Spec
+specLookupSeq = describe "Test for lookupSeq" $ do
+  it "Compare lookup by ID with by SubSeq" $
+    lookupSeq (ID "A000027") `shouldBe` lookupSeq (SubSeq [1, 2, 3, 4, 5, 6, 7])
+  prop "Compare lookup by ID with by SubSeq -2" $
+    \x ->
+    let rs   = unsafePerformIO $ generate $ resize 5 $ vectorOf x $ choose (1, 10)
+        seq1 = lookupSeq (SubSeq rs)
+        num  = maybe "" number seq1
+        seq2 = lookupSeq (ID num)
+    in seq2 `shouldBe` seq1
+  it "Get Maple function" $
+    maple <$> lookupSeq (ID "A000027") `shouldBe`
+    Just ["A000027 := n->n; seq(A000027(n), n=1..100);"]
+  it "No search results" $
+    lookupSeq (SubSeq [1,3,4,5,4,3,6]) `shouldBe` Nothing
+
+specGetSeqData :: Spec
+specGetSeqData = describe "Test for getSeqData" $ do
+  it "Get SeqData" $
+    getSeqData (ID "A000027")`shouldBe` Just [1..77]
+  it "No SeqData" $
+    getSeqData (SubSeq [1,3,4,5,4,3,6]) `shouldBe` Nothing
+
+specExtendSeq :: Spec
+specExtendSeq = describe "Test for extendSeq" $ do
+  prop "Extend Seq" $
+    \x ->
+    let rs = unsafePerformIO $ generate $ resize 5 $ vectorOf x $ choose (1, 10)
+        seq = extendSeq rs
+    in rs `isInfixOf` seq
+  it "No extension" $
+    extendSeq [1,3,4,5,4,3,6] `shouldBe` [1,3,4,5,4,3,6]
+
