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 +1/−0
- ghc-src/Web/HackerNews.hs +43/−21
- ghc-tests/Test.hs +0/−53
- ghcjs-tests/Test.hs +0/−53
- hackernews.cabal +19/−21
- src/Web/HackerNews/Types.hs +61/−40
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