packages feed

hackernews 1.0.0.0 → 1.1.0.0

raw patch · 6 files changed

+124/−188 lines, 6 filesdep −basic-sopdep −generics-sopdep −transformersdep ~QuickCheckdep ~aesondep ~hackernewsPVP ok

version bump matches the API change (PVP)

Dependencies removed: basic-sop, generics-sop, transformers

Dependency ranges changed: QuickCheck, aeson, hackernews, hspec, http-client, http-client-tls, quickcheck-instances, servant, servant-client

API changes (from Hackage documentation)

- Web.HackerNews: instance (Web.HttpApiData.Internal.ToHttpApiData a, Servant.Client.HasClient api) => Servant.Client.HasClient (Web.HackerNews.HackerCapture a Servant.API.Sub.:> api)
- Web.HackerNews.Types: instance Web.HttpApiData.Internal.ToHttpApiData Web.HackerNews.Types.ItemId
- Web.HackerNews.Types: instance Web.HttpApiData.Internal.ToHttpApiData Web.HackerNews.Types.UserId
+ Web.HackerNews: instance (Web.Internal.HttpApiData.ToHttpApiData a, Servant.Client.HasClient api) => Servant.Client.HasClient (Web.HackerNews.HackerCapture a Servant.API.Sub.:> api)
+ Web.HackerNews.Types: instance GHC.Enum.Enum Web.HackerNews.Types.ItemType
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.About
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.AskStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.BestStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Created
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Dead
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Delay
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Deleted
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Descendants
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Item
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.ItemId
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.ItemText
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.ItemType
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.JobStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Karma
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Kids
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.MaxItem
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.NewStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Parent
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Parts
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Score
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.ShowStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Submitted
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Time
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Title
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.TopStories
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.URL
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.Updates
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.User
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.UserId
+ Web.HackerNews.Types: instance Test.QuickCheck.Arbitrary.Arbitrary Web.HackerNews.Types.UserName
+ Web.HackerNews.Types: instance Web.Internal.HttpApiData.ToHttpApiData Web.HackerNews.Types.ItemId
+ Web.HackerNews.Types: instance Web.Internal.HttpApiData.ToHttpApiData Web.HackerNews.Types.UserId
- Web.HackerNews: AskStories :: [Int] -> AskStories
+ Web.HackerNews: AskStories :: [ItemId] -> AskStories
- Web.HackerNews: BestStories :: [Int] -> BestStories
+ Web.HackerNews: BestStories :: [ItemId] -> BestStories
- Web.HackerNews: Deleted :: Int -> Deleted
+ Web.HackerNews: Deleted :: Bool -> Deleted
- Web.HackerNews: JobStories :: [Int] -> JobStories
+ Web.HackerNews: JobStories :: [ItemId] -> JobStories
- Web.HackerNews: Kids :: [Int] -> Kids
+ Web.HackerNews: Kids :: [ItemId] -> Kids
- Web.HackerNews: MaxItem :: Int -> MaxItem
+ Web.HackerNews: MaxItem :: ItemId -> MaxItem
- Web.HackerNews: NewStories :: [Int] -> NewStories
+ Web.HackerNews: NewStories :: [ItemId] -> NewStories
- Web.HackerNews: Parent :: Int -> Parent
+ Web.HackerNews: Parent :: ItemId -> Parent
- Web.HackerNews: Parts :: [Int] -> Parts
+ Web.HackerNews: Parts :: [ItemId] -> Parts
- Web.HackerNews: ShowStories :: [Int] -> ShowStories
+ Web.HackerNews: ShowStories :: [ItemId] -> ShowStories
- Web.HackerNews: Submitted :: [Int] -> Submitted
+ Web.HackerNews: Submitted :: [ItemId] -> Submitted
- Web.HackerNews: TopStories :: [Int] -> TopStories
+ Web.HackerNews: TopStories :: [ItemId] -> TopStories
- Web.HackerNews: Updates :: [Int] -> [UserName] -> Updates
+ Web.HackerNews: Updates :: [ItemId] -> [UserName] -> Updates
- Web.HackerNews: [items] :: Updates -> [Int]
+ Web.HackerNews: [items] :: Updates -> [ItemId]
- Web.HackerNews.Types: AskStories :: [Int] -> AskStories
+ Web.HackerNews.Types: AskStories :: [ItemId] -> AskStories
- Web.HackerNews.Types: BestStories :: [Int] -> BestStories
+ Web.HackerNews.Types: BestStories :: [ItemId] -> BestStories
- Web.HackerNews.Types: Deleted :: Int -> Deleted
+ Web.HackerNews.Types: Deleted :: Bool -> Deleted
- Web.HackerNews.Types: JobStories :: [Int] -> JobStories
+ Web.HackerNews.Types: JobStories :: [ItemId] -> JobStories
- Web.HackerNews.Types: Kids :: [Int] -> Kids
+ Web.HackerNews.Types: Kids :: [ItemId] -> Kids
- Web.HackerNews.Types: MaxItem :: Int -> MaxItem
+ Web.HackerNews.Types: MaxItem :: ItemId -> MaxItem
- Web.HackerNews.Types: NewStories :: [Int] -> NewStories
+ Web.HackerNews.Types: NewStories :: [ItemId] -> NewStories
- Web.HackerNews.Types: Parent :: Int -> Parent
+ Web.HackerNews.Types: Parent :: ItemId -> Parent
- Web.HackerNews.Types: Parts :: [Int] -> Parts
+ Web.HackerNews.Types: Parts :: [ItemId] -> Parts
- Web.HackerNews.Types: ShowStories :: [Int] -> ShowStories
+ Web.HackerNews.Types: ShowStories :: [ItemId] -> ShowStories
- Web.HackerNews.Types: Submitted :: [Int] -> Submitted
+ Web.HackerNews.Types: Submitted :: [ItemId] -> Submitted
- Web.HackerNews.Types: TopStories :: [Int] -> TopStories
+ Web.HackerNews.Types: TopStories :: [ItemId] -> TopStories
- Web.HackerNews.Types: Updates :: [Int] -> [UserName] -> Updates
+ Web.HackerNews.Types: Updates :: [ItemId] -> [UserName] -> Updates
- Web.HackerNews.Types: [items] :: Updates -> [Int]
+ Web.HackerNews.Types: [items] :: Updates -> [ItemId]

Files

README.md view
@@ -52,6 +52,7 @@  main :: IO () main = do+ mgr <- newManager tlsManagerSettings  print =<< getItem mgr (ItemId 1000)  print =<< getUser mgr (UserId "dmjio")  print =<< getMaxItem mgr
ghc-src/Web/HackerNews.hs view
@@ -71,7 +71,6 @@   , HackerNewsError (..)   ) where -import           Control.Monad.Trans.Except import           Data.Bifunctor import           Data.Monoid import           Data.Proxy@@ -131,76 +130,99 @@     go (ConnectionError ex) =       HNConnectionError $ cs (show ex) +mkClientEnv :: Manager -> ClientEnv+mkClientEnv = flip ClientEnv hackerNewsURL+ -- | Retrieve `Item` getItem :: Manager -> ItemId -> IO (Either HackerNewsError Item) getItem mgr itemId =   toError <$> do-    runExceptT $ getItem' itemId mgr hackerNewsURL+    runClientM+      (getItem' itemId)+      (mkClientEnv mgr)  -- | Retrieve `User` getUser :: Manager -> UserId -> IO (Either HackerNewsError User) getUser mgr userId =   toError <$> do-    runExceptT $ getUser' userId mgr hackerNewsURL+    runClientM+      (getUser' userId)+      (ClientEnv mgr hackerNewsURL)  -- | Retrieve `MaxItem` getMaxItem :: Manager -> IO (Either HackerNewsError MaxItem) getMaxItem mgr =   toError <$> do-    runExceptT $ getMaxItem' mgr hackerNewsURL+    runClientM+      getMaxItem'+      (ClientEnv mgr hackerNewsURL)  -- | Retrieve `TopStories` getTopStories :: Manager -> IO (Either HackerNewsError TopStories) getTopStories mgr =   toError <$> do-    runExceptT $ getTopStories' mgr hackerNewsURL+    runClientM+      getTopStories'+      (mkClientEnv mgr)  -- | Retrieve `NewStories` getNewStories :: Manager -> IO (Either HackerNewsError NewStories) getNewStories mgr =   toError <$> do-    runExceptT $ getNewStories' mgr hackerNewsURL+    runClientM+      getNewStories'+      (mkClientEnv mgr)  -- | Retrieve `BestStories` getBestStories :: Manager -> IO (Either HackerNewsError BestStories) getBestStories mgr =   toError <$> do-    runExceptT $ getBestStories' mgr hackerNewsURL+    runClientM+      getBestStories'+      (mkClientEnv mgr)  -- | Retrieve `AskStories` getAskStories :: Manager -> IO (Either HackerNewsError AskStories) getAskStories mgr =   toError <$> do-    runExceptT $ getAskStories' mgr hackerNewsURL+    runClientM+      getAskStories'+      (mkClientEnv mgr)  -- | Retrieve `ShowStories` getShowStories :: Manager -> IO (Either HackerNewsError ShowStories) getShowStories mgr =   toError <$> do-    runExceptT $ getShowStories' mgr hackerNewsURL+    runClientM+      getShowStories'+      (mkClientEnv mgr)  -- | Retrieve `JobStories` getJobStories :: Manager -> IO (Either HackerNewsError JobStories) getJobStories mgr =   toError <$> do-    runExceptT $ getJobStories' mgr hackerNewsURL+    runClientM+      getJobStories'+      (mkClientEnv mgr)  -- | Retrieve `Updates` getUpdates :: Manager -> IO (Either HackerNewsError Updates) getUpdates mgr =   toError <$> do-    runExceptT $ getUpdates' mgr hackerNewsURL+    runClientM+      getUpdates'+      (mkClientEnv mgr) -getItem' :: ItemId -> Manager -> BaseUrl -> ClientM Item-getUser' :: UserId -> Manager -> BaseUrl -> ClientM User-getMaxItem' :: Manager -> BaseUrl -> ClientM MaxItem-getTopStories' :: Manager -> BaseUrl -> ClientM TopStories-getNewStories' :: Manager -> BaseUrl -> ClientM NewStories-getBestStories' :: Manager -> BaseUrl -> ClientM BestStories-getAskStories' :: Manager -> BaseUrl -> ClientM AskStories-getShowStories' :: Manager -> BaseUrl -> ClientM ShowStories-getJobStories' :: Manager -> BaseUrl -> ClientM JobStories-getUpdates' :: Manager -> BaseUrl -> ClientM Updates+getItem' :: ItemId -> ClientM Item+getUser' :: UserId -> ClientM User+getMaxItem' :: ClientM MaxItem+getTopStories' :: ClientM TopStories+getNewStories' :: ClientM NewStories+getBestStories' :: ClientM BestStories+getAskStories' :: ClientM AskStories+getShowStories' :: ClientM ShowStories+getJobStories' :: ClientM JobStories+getUpdates' ::  ClientM Updates  getItem'   :<|> getUser'
ghc-tests/Test.hs view
@@ -3,67 +3,14 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Main where -import Control.Applicative import Data.Aeson import Data.Either               (isRight)-import Generics.SOP.Arbitrary-import Generics.SOP.Universe import Network.HTTP.Client import Network.HTTP.Client.TLS import Test.Hspec                (it, hspec, describe, shouldSatisfy, shouldBe) import Test.QuickCheck import Test.QuickCheck.Instances () import Web.HackerNews--instance Generic Item-instance Generic Updates-instance Generic User-instance Generic UserName-instance Generic UserId-instance Generic Delay-instance Generic Created-instance Generic Karma-instance Generic About-instance Generic Submitted--instance Arbitrary Item where arbitrary = garbitrary-instance Arbitrary User where arbitrary = garbitrary-instance Arbitrary Updates where arbitrary = garbitrary--instance Arbitrary UserName where arbitrary = garbitrary-instance Arbitrary UserId  where arbitrary = garbitrary-instance Arbitrary Delay where arbitrary = garbitrary-instance Arbitrary Created where arbitrary = garbitrary-instance Arbitrary Karma where arbitrary = garbitrary-instance Arbitrary About where arbitrary = garbitrary-instance Arbitrary Submitted where arbitrary = garbitrary--instance Arbitrary ItemId where arbitrary = garbitrary-instance Generic ItemId-instance Arbitrary Deleted where arbitrary = garbitrary-instance Generic Deleted-instance Arbitrary ItemType where arbitrary = garbitrary-instance Generic ItemType where-instance Arbitrary Time where arbitrary = garbitrary-instance Generic Time-instance Arbitrary ItemText where arbitrary = garbitrary-instance Generic ItemText-instance Arbitrary Dead where arbitrary = garbitrary-instance Generic Dead-instance Arbitrary Parent where arbitrary = garbitrary-instance Generic Parent-instance Arbitrary Kids where arbitrary = garbitrary-instance Generic Kids-instance Arbitrary URL where arbitrary = garbitrary-instance Generic URL-instance Arbitrary Score where arbitrary = garbitrary-instance Generic Score-instance Arbitrary Title where arbitrary = garbitrary-instance Generic Title-instance Arbitrary Parts where arbitrary = garbitrary-instance Generic Parts-instance Arbitrary Descendants where arbitrary = garbitrary-instance Generic Descendants  main :: IO () main = do
ghcjs-tests/Test.hs view
@@ -8,66 +8,13 @@ import Data.Aeson import Data.Either               (isRight) import Data.JSString-import Generics.SOP.Arbitrary-import Generics.SOP.Universe import System.Exit import Test.Hspec (it, hspec, describe, shouldSatisfy, shouldBe) import Test.Hspec.Core.Runner (hspecResult, Summary(..)) import Test.QuickCheck-import Test.QuickCheck.Instances ()  import Web.HackerNews.Types import Web.HackerNews--instance Generic Item-instance Generic Updates-instance Generic User-instance Generic UserName-instance Generic UserId-instance Generic Delay-instance Generic Created-instance Generic Karma-instance Generic About-instance Generic Submitted--instance Arbitrary Item where arbitrary = garbitrary-instance Arbitrary User where arbitrary = garbitrary-instance Arbitrary Updates where arbitrary = garbitrary--instance Arbitrary UserName where arbitrary = garbitrary-instance Arbitrary UserId  where arbitrary = garbitrary-instance Arbitrary Delay where arbitrary = garbitrary-instance Arbitrary Created where arbitrary = garbitrary-instance Arbitrary Karma where arbitrary = garbitrary-instance Arbitrary About where arbitrary = garbitrary-instance Arbitrary Submitted where arbitrary = garbitrary--instance Arbitrary ItemId where arbitrary = garbitrary-instance Generic ItemId-instance Arbitrary Deleted where arbitrary = garbitrary-instance Generic Deleted-instance Arbitrary ItemType where arbitrary = garbitrary-instance Generic ItemType where-instance Arbitrary Time where arbitrary = garbitrary-instance Generic Time-instance Arbitrary ItemText where arbitrary = garbitrary-instance Generic ItemText-instance Arbitrary Dead where arbitrary = garbitrary-instance Generic Dead-instance Arbitrary Parent where arbitrary = garbitrary-instance Generic Parent-instance Arbitrary Kids where arbitrary = garbitrary-instance Generic Kids-instance Arbitrary URL where arbitrary = garbitrary-instance Generic URL-instance Arbitrary Score where arbitrary = garbitrary-instance Generic Score-instance Arbitrary Title where arbitrary = garbitrary-instance Generic Title-instance Arbitrary Parts where arbitrary = garbitrary-instance Generic Parts-instance Arbitrary Descendants where arbitrary = garbitrary-instance Generic Descendants  main :: IO () main = do
hackernews.cabal view
@@ -1,5 +1,5 @@ name:                hackernews-version:             1.0.0.0+version:             1.1.0.0 description:         API for news.ycombinator.com license:             MIT synopsis:            API for Hacker News@@ -23,13 +23,13 @@   if impl (ghcjs)     build-depends:         base-      , hackernews == 1.0.*+      , hackernews == 1.1.*       , ghcjs-base     hs-source-dirs: ghcjs-examples   else     build-depends:          base-       , hackernews == 1.0.*+       , hackernews == 1.1.*        , http-client-tls        , http-client     hs-source-dirs: ghc-examples@@ -39,15 +39,13 @@   if impl(ghcjs)     hs-source-dirs: ghcjs-tests     build-depends: base-               , hackernews == 1.0.*+               , hackernews == 1.1.*                , ghcjs-base                , hspec                , hspec-core-               , basic-sop-               , generics-sop                , quickcheck-instances                , aeson-                 , QuickCheck+               , QuickCheck   else     buildable: False   default-language: Haskell2010@@ -56,47 +54,47 @@   exposed-modules:  Web.HackerNews                   , Web.HackerNews.Types   hs-source-dirs: src-  build-depends: servant == 0.8.*+  build-depends:+      servant == 0.9.*+    , QuickCheck+    , quickcheck-instances   if impl(ghcjs)     ghcjs-options:  -Wall     hs-source-dirs: ghcjs-src-    build-depends:  aeson == 0.9.*+    build-depends:  aeson                   , attoparsec == 0.13.*                   , base < 5                   , ghcjs-base                   , string-conversions == 0.4.*                   , text == 1.2.*-                  , transformers == 0.4.*   else     ghc-options:  -Wall     hs-source-dirs: ghc-src     build-depends: aeson                  , base < 5-                 , servant-client == 0.8.*-                 , http-client == 0.4.*+                 , servant-client == 0.9.*+                 , http-client == 0.5.*                  , string-conversions == 0.4.*                  , http-types == 0.9.*                  , text == 1.2.*-                 , transformers == 0.5.*   default-language:    Haskell2010  Test-Suite ghc-tests   type:                exitcode-stdio-1.0+  if impl(ghcjs)+    buildable: False   default-language:    Haskell2010   main-is:             Test.hs   ghc-options:         -rtsopts -threaded -Wall   hs-source-dirs:      ghc-tests   build-depends:       aeson                      , base-                     , basic-sop-                     , generics-sop == 0.2.*-                     , hackernews == 1.0.*-                     , hspec == 2.2.*-                     , http-client-tls == 0.2.*+                     , hackernews == 1.1.*+                     , hspec == 2.3.*+                     , http-client-tls                      , http-client-                     , QuickCheck == 2.8.*-                     , quickcheck-instances == 0.3.*-                     , transformers+                     , QuickCheck+                     , quickcheck-instances  source-repository head   type:     git
src/Web/HackerNews/Types.hs view
@@ -20,9 +20,12 @@ import           GHC.Generics import           Servant.API +import Test.QuickCheck+import Test.QuickCheck.Instances ()+ -- | The item and profile changes are at <https://hacker-news.firebaseio.com/v0/updates> data Updates = Updates  {-      items :: [Int]+      items :: [ItemId]        -- ^ Updated `Item`s     , profiles :: [UserName]        -- ^ Updated `UserName`s@@ -31,34 +34,37 @@ instance ToJSON Updates instance FromJSON Updates +instance Arbitrary Updates where+  arbitrary = Updates <$> arbitrary <*> arbitrary+ -- | The current largest item id is at <https://hacker-news.firebaseio.com/v0/maxitem>. -- You can walk backward from here to discover all items.-newtype MaxItem = MaxItem Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype MaxItem = MaxItem ItemId+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/topstories>-newtype TopStories = TopStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype TopStories = TopStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/newstories>-newtype NewStories = NewStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype NewStories = NewStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/beststories>-newtype BestStories = BestStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype BestStories = BestStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/askstories>-newtype AskStories = AskStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype AskStories = AskStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/showstories>-newtype ShowStories = ShowStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype ShowStories = ShowStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | <https://hacker-news.firebaseio.com/v0/jobstories>-newtype JobStories = JobStories [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype JobStories = JobStories [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | Users are identified by case-sensitive ids, and live under -- <https://hacker-news.firebaseio.com/v0/user/>.@@ -79,6 +85,11 @@     -- ^ List of the user's stories, polls and comments.   } deriving (Show, Eq, Generic) +instance Arbitrary User where+  arbitrary =+    User <$> arbitrary <*> arbitrary <*> arbitrary+         <*> arbitrary <*> arbitrary <*> arbitrary+ instance ToJSON User where   toJSON = genericToJSON defaultOptions {     fieldLabelModifier = map toLower . drop 4@@ -91,40 +102,43 @@  -- | The user's karma. newtype Karma = Karma Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The user's unique username. Case-sensitive. Required. newtype UserId = UserId T.Text-  deriving (Show, Eq, ToJSON, FromJSON, ToHttpApiData, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, ToHttpApiData, Generic, Arbitrary)  -- | Delay in minutes between a comment's creation and its visibility to other users. newtype Delay = Delay Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | Creation date of the user, in Unix Time. newtype Created = Created Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The user's optional self-description. HTML. newtype About = About T.Text-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | List of the user's stories, polls and comments.-newtype Submitted = Submitted [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype Submitted = Submitted [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The item's unique id. newtype ItemId = ItemId Int-  deriving (Show, Eq, ToJSON, FromJSON, ToHttpApiData, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, ToHttpApiData, Generic, Arbitrary)  -- | `true` if the item is deleted.-newtype Deleted = Deleted Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype Deleted = Deleted Bool+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The type of item. One of "job", "story", "comment", "poll", or "pollopt" data ItemType = Job | Story | Comment | Poll | PollOpt-  deriving (Show, Eq, Generic)+  deriving (Show, Eq, Generic, Enum) +instance Arbitrary ItemType where+  arbitrary = elements [ Job .. ]+ instance ToJSON ItemType where   toJSON = genericToJSON     defaultOptions { constructorTagModifier = map toLower }@@ -135,48 +149,48 @@  -- | The username of the item's author. newtype UserName = UserName T.Text-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The comment, story or poll text. HTML. newtype ItemText = ItemText T.Text-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | `true` if the item is dead. newtype Dead = Dead Bool-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The item's parent. For comments, either another comment or the relevant story. -- For pollopts, the relevant poll.-newtype Parent = Parent Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype Parent = Parent ItemId+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | Creation date of the item, in Unix Time. newtype Time = Time Integer-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The ids of the item's comments, in ranked display order.-newtype Kids = Kids [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype Kids = Kids [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The URL of the story. newtype URL = URL T.Text-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The story's score, or the votes for a pollopt. newtype Score = Score Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | The title of the story, poll or job. newtype Title = Title T.Text-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | A list of related pollopts, in display order.-newtype Parts = Parts [Int]-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+newtype Parts = Parts [ItemId]+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | In the case of stories or polls, the total comment count. newtype Descendants = Descendants Int-  deriving (Show, Eq, ToJSON, FromJSON, Generic)+  deriving (Show, Eq, ToJSON, FromJSON, Generic, Arbitrary)  -- | Stories, comments, jobs, Ask HNs and even polls are just items. -- They're identified by their ids, which are unique integers, and live under@@ -197,6 +211,13 @@     , itemParts       :: Maybe Parts     , itemDescendants :: Maybe Descendants     } deriving (Show, Eq, Generic)++instance Arbitrary Item where+  arbitrary = Item <$> arbitrary <*> arbitrary <*> arbitrary+                   <*> arbitrary <*> arbitrary <*> arbitrary+                   <*> arbitrary <*> arbitrary <*> arbitrary+                   <*> arbitrary <*> arbitrary <*> arbitrary+                   <*> arbitrary <*> arbitrary  instance ToJSON Item where   toJSON = genericToJSON