packages feed

oeis2 (empty) → 0.1.0

raw patch · 9 files changed

+660/−0 lines, 9 filesdep +QuickCheckdep +aesondep +basesetup-changed

Dependencies added: QuickCheck, aeson, base, containers, hspec, http-conduit, lens, lens-aeson, oeis2, text, vector

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for oeis++## Unreleased changes
+ LICENSE view
@@ -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.
+ README.md view
@@ -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).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ oeis2.cabal view
@@ -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
+ src/Math/OEIS.hs view
@@ -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
+ src/Math/OEIS/Internal.hs view
@@ -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'
+ src/Math/OEIS/Types.hs view
@@ -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)
+ test/Spec.hs view
@@ -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]+