Services at Klarna written in Haskell
We’re not officially supporting it.
servant
postgresql-simple (+ opalaye)
hedgehog
A set of packages to declare web APIs on the type-level
type GetPet
= "pets" :> Capture "petId" PetId :> Get '[JSON] Pet
type GetPet
= "pets" :> Capture "petId" PetId :> Get '[JSON] Pet
type PostPet
= "pets" :> Capture "petId" PetId :> Post '[JSON] NoContent
:> ReqBody '[JSON] Pet
type GetPet
= "pets" :> Capture "petId" PetId :> Get '[JSON] Pet
type PostPet
= "pets" :> Capture "petId" PetId :> Post '[JSON] NoContent
:> ReqBody '[JSON] Pet
type PetAPI
= GetPet
:<|> PostPet
:<|> DeletePet
type PetApi = ...
petApiSwagger = encode $ toSwagger $ Proxy @UserApi
type PetApi = ...
petApiSwagger = encode $ toSwagger $ Proxy @UserApi
-- error:
-- • No instance for (ToSchema Pet)
-- arising from a use of ‘toSwagger’
-- • In the second argument of ‘($)’, namely
-- ‘toSwagger $ Proxy @GetPet’
-- In the expression: encode $ toSwagger $ Proxy @GetPet
-- In an equation for ‘swaggy’:
-- swaggy = encode $ toSwagger $ Proxy @GetPet
data Pet = Pet
{ name :: Text
, age :: Int
}
deriving (Generic)
data Pet = Pet
{ name :: Text
, age :: Int
}
deriving (Generic)
instance ToSchema Pet
type PetApi = ...
petApiSwagger = encode $ toSwagger $ Proxy @UserApi
-- { "swagger": "2.0", ... }
type PetApi = ...
getPetClient :: PetId -> ClientM Pet
postPetClient :: PetId -> Pet -> ClientM NoContent
getPetClient :<|> postPetClient = client (Proxy @PetApi)
getPet :: ClientEnv -> PetId -> IO (Either ClientError Pet)
getPet env petId = runClientM (getPetClient petId) env
import Servant.JS (jsForApi)
import Servant.JS.Axios (axios)
type PetApi = ...
jsCode :: String
jsCode = jsForApi (Proxy @PetApi) axios
apiDocs :: String
apiDocs = _ $ docs $ Proxy @PetApi
apiDocs :: String
apiDocs = markdown $ docs $ Proxy @PetApi
apiDocs :: String
apiDocs = _ $ pandoc $ docs $ Proxy @PetApi
AsciiDoc, CommonMark, ConTeXt, Custom, Docbook, Docx, DokuWiki, EPUB, FB2, HTML, Haddock, ICML, Ipynb, JATS, Jira, LaTeX, Man, Markdown, Math, MediaWiki, Ms, Muse, Native, ODT, OOXML, OPML, OpenDocument, Org, Powerpoint, RST, RTF, Shared, TEI, Texinfo, Textile, XWiki, ZimWiki
petGen :: Gen Pet
= Pet
<$> choice [ "Diddy", "Tupac" ]
<*> Gen.int (Range 0 10)
import Servant.Mock
petApi :: Proxy PetApi
petApi = Proxy
main :: IO ()
main = run 8080 $ serve petApi (mock petApi Proxy)
import Hedgehog.Servant
genApi :: Gen (BaseUrl -> Request)
genApi = genRequest (Proxy @PetApi) (genPet :*: GNil)
type GetPet
= "pets" :> Capture "petId" PetId :> Get '[JSON] Pet
getPet :: PetId -> Maybe Pet
getPet :: PetId -> Maybe Pet
getPet :: PetId -> Maybe Pet
-- Which we'll translate to:
getPet :: PetId -> Handler Pet
pets :: Map PetId Pet
pets = Map.fromList
[ ("cat", undefined)
, ("dog", undefined)
]
getPet :: PetId -> Handler Pet
getPet petId =
case Map.lookup petId of
Just pet -> return pet
Nothing -> throw404
apiHandler :: Server PetApi
apiHandler
= getPet
:<|> postPet
main :: IO ()
main
= run 8080
$ serve (Proxy @PetApi) apiHandlers
Getting stuff done is quick, and sans footguns
We’re really happy with what Haskell offers us
Build the next generation of banking using FP