News aggregator

Haskell dev roles with Strats at Standard Chartered

haskell-cafe - Mon, 01/18/2016 - 12:21pm
Hi folks, I'm hiring 3 more devs to write Haskell for Standard Chartered in London and Singapore. Details of the roles below, but broadly in FX algo pricing and pricing automation. Ability to write "tight" total Haskell that can run 24/7 and do the right thing is needed. https://donsbot.wordpress.com/2016/01/18/haskell-developer-roles-at-standard-chartered-london-singapore/ CVs to me at Standard Chartered
Categories: Offsite Discussion

Spock Web Framework and SSL

Haskell on Reddit - Mon, 01/18/2016 - 11:40am

The Spock web framework lacks any reference on how to enable SSL (https) support in it. Does anyone have any reference on how to do that?

submitted by thesz
[link] [7 comments]
Categories: Incoming News

Darcs: darcs hacking sprint 10 report

Planet Haskell - Mon, 01/18/2016 - 10:57am
Last weekend we had our tenth Darcs sprint, and our first one in Spain. This time indeed, the sprint was organised in the University of Seville, ETSII (Technical Superior School of Informatics Engineering), on January 15th to 17th.



We were 3 participants: Florent Becker, Guillaume Hoffmann and Ganesh Sittampalam. We also had Pierre-Étienne Meunier on video call and Simon Michael on IRC.


Darcs and Pijul integration
One major topic during the whole sprint was the possible integration of Darcs with Pijul. Pijul is a new version control system based on a different patch theory, whose main author is Pierre-Étienne Meunier. Florent also contributes to Pijul and announced its first release last October.

Pijul is promising in terms of how it handles conflicts in a better way than Darcs (better as: better presentation to the user and better performance). There may be a future where Darcs uses Pijul patches by default.  We had many conversations with Florent to understand the internals of Pijul and how it manages patches.

On the first day of the sprint we did a video call with Pierre-Étienne Meunier, to discuss integration of Pijul core with Darcs. It happens that the Darcs code is modular enough to handle Pijul patches (with some work). That afternoon Florent started to work on a Haskell binding for libpijul (through a C binding maintained by Pierre-Étienne, Pijul being implemented in Rust).

Ganesh, Florent and Pierre-Étienne are going to work towards a better integration of both systems. Pierre-Étienne plans to release a 0.2 version of Pijul soon.


Ganesh and Florent with Pierre-Étienne on video callRenaming Patch/RealPatch to RepoPatchV1/RepoPatchV2The code of Darcs contains many different layers of patch types. One of them is represented by the two types Patch and RealPatch, and specifies the behaviour of named patch when they are commuted and in case of conflicts. The "Patch" type is the behaviour of patches in repositories with the darcs-1 patch semantics (which can still be created by Darcs) and "RealPatch" is for darcs-2 semantics (the current default of Darcs). I sent a patch to rename these types into something less confusing: RepoPatchV1 and RepoPatchV2.


Interactive selection performance and refactoringEven if we wrote a patch that improved greatly performance during the last sprint (and we now have a unit test for it), the command "darcs rollback -p ." still remains much slower than "darcs rollback" before presenting the first choice of patch to the user. Florent determined that this was because the action of matching patches within interactive selection is not lazy, ie, the whole list of patches has to be scanned and classified before the first prompt is shown to the user. Florent unearthed a refactor he had of the patch selection code and started rebasing it against the current code.


User manual and developer handbookWe want Darcs to have a user manual again, and a developer handbook that would compile documentation for programmers and computer scientists. We decided the manual should live in darcs' repository itself (so that it stays up-to-date) and the developer handbook on the wiki.

Darcs on StackageOn IRC, Simon Michael (after an initial request by Joachim Breitner) committed himself to maintain a stack.yaml file for Darcs, and during the weekend Darcs was added to stackage for easier building.


Cleanup, fixes and refactoringsGanesh tracked down bugs in rebase and sent a few cleanup patches. Moreover he's improving the code of "darcs test" (formerly called "darcs trackdown") so that uncompilable states are neither considered as Passing nor Failing, and bisect is going to be more efficient.


What happens nextI am going to release Darcs 2.10.3 within a couple of weeks, and Darcs 2.12 within a couple of months. This new major version will have optimizations (some of them are already backported to the 2.10 branch) and code refactorings. It may contain the stash feature currently developed by Ganesh. 

This year we hope to have another sprint, and to have more developers participating. Please consult the How to Help, Developer's Getting Started and Projects page on the wiki to get involved!

Ganesh, Florent and Guillaume


Categories: Offsite Blogs

Don Stewart (dons): Haskell developer roles at Standard Chartered [London, Singapore]

Planet Haskell - Mon, 01/18/2016 - 7:25am

The Strats team at Standard Chartered has three open positions for typed functional programming developers, based in London and Singapore. Strats are a specialized software engineering and quantitative analysis team who build a broad range of software for financial markets users at Standard Chartered.

You will work on the trading floor, directly with traders, building software to automate their work and improve their efficiency. The focus of these role will be on market pricing feed automation and algorithmic pricing.

You will use Haskell for almost all tasks: data analysis, market data publishing, database access, web services, desktop GUIs, large parallel tasks, quantitative models, solvers, everything. This is a fast paced role – code you write today will be deployed within hours to hundreds of users and has to work. 

These are permanent, associate director and director positions, in London and Singapore as part of the Strats global team. Demonstrated experience in typed FP (Haskell, OCaml, F# etc) is required. We have around 3 million lines of Haskell, and our own Haskell compiler. In this context we look for skill and taste in typed functional programming to capture and abstract over complex, messy systems.

Experience writing typed APIs to external systems such as databases, web services, pub/sub platforms is very desirable. We like working code, so if you have Hackage or github libraries, we definitely want to see them. We also like StackOverflow answers, blog posts, academic papers, or other arenas where you can show broad FP ability. A PhD in computer science is a strong advantage.

The role requires physical presence on the trading floor in Singapore or London. Remote work is not an option. You will have some project and client management skills — you will talk to users, understand their problems and then implement and deliver what they really need. No financial background is required. These positions have attractive remuneration for the right candidates. Relocation support will also be provided. Contracting-based positions are also possible if desired.

Applicants who don’t necessarily meet all criteria but have an interest in working in Singapore in particular, and have an FP background, are encouraged to apply.

More info about our development process is in the 2012 PADL keynote, and a 2013 HaskellCast interview.

If this sounds exciting to you, please send your resume to me – donald.stewart <at> sc.com.


Tagged: jobs
Categories: Offsite Blogs

Proposal: Data.Bool.implies

libraries list - Mon, 01/18/2016 - 4:17am
I propose to add to Data.Bool: -- | Boolean implication. implies :: Bool -> Bool -> Bool implies True x = x implies False _ = True infix 4 `implies` -- same as (==) The request for this is quite old (see e.g. http://neilmitchell.blogspot.de/2007/02/logical-implication-in-haskell.html). I believe that by not trying to use an operator for it, and keeping it in Data.Bool, we can avoid doing anything wrong. A quick superficial search on Stackage Hoogle suggests that adding this function should create no breakage (4 packages define their own function called `implies`, none of them import Data.Bool). `infix` instead of `infixl` or `infixr` to force you to bracket it; for the same reason it has the same precedence as `==`.
Categories: Offsite Discussion

Fun With RULES

Haskell on Reddit - Mon, 01/18/2016 - 3:41am
Categories: Incoming News

project compile with multi-versions of alex

haskell-cafe - Mon, 01/18/2016 - 2:48am
Hi Cafe, I have a Haskell project which has ~90 dependencies (transitively) and is managed with plain cabal (w/o stackage, etc.). I try to keep it compile with a few latest releases of GHC (so right now 7.8.4, 7.10.1, 7.10.2 and 7.10.3). It was tractable with conditionals in the cabal config file with minor annoyance. But recently I found this issue:language-c-quote-0.11.3 does not compile with alex 3.1.5 [1]. I was wondering if I should also allow a few versions of executables, like alex, happy, etc (I can see though it will be a huge pain); or should I force all users to use the latest versions of them (I don't know if they are compatible with old ghc versions)? What's the common practice for other projects? Any hints? What should I write in my cabal config? Thanks, Zilin [1]https://github.com/mainland/language-c-quote/issues/57 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe< at >haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Categories: Offsite Discussion

How to build Haddock git master?

Haskell on Reddit - Sun, 01/17/2016 - 11:34pm

I think I need to patch Haddock quite a lot to fully realize my ideas for this theme. I'd like to use the Haddock's git master as the base so that I can hopefully make a pull request, but it seems to require latest GHC beta, and there are no instructions on how to get it.

submitted by lamefun
[link] [2 comments]
Categories: Incoming News

Haskell for Finance resources

Haskell on Reddit - Sun, 01/17/2016 - 11:17pm

I'm looking for resources that discuss Haskell in the context of finance. A few that I know about:

This list is fairly limited. Are there any other resources that are interesting to list?

submitted by stasiana
[link] [9 comments]
Categories: Incoming News

lts-4 with aeson-0.10 is being discontinued, lts-5 will use aeson-0.9

Haskell on Reddit - Sun, 01/17/2016 - 7:56pm

Thank you for this discussion the other day. What I saw there confirmed the general consensus among stackage curators about how to approach this situation.

The switch back to aeson-0.9 has a few bumps, tracked here. I'd like to thank the package authors that have the patience to work with us on this.

Tonight lts-4.2 will be released. After that, we don't anticipate any updates to the lts-4 series. Normally, an LTS is supported for a minimum of 3 months, but we feel this exception is appropriate. Next week, lts-5.0 will be released, and we hope that it will help prevent issues like this one.

submitted by drb226
[link] [17 comments]
Categories: Incoming News

Statically linking Haskell executables and glibc

Haskell on Reddit - Sun, 01/17/2016 - 3:23pm

When I compile a simple application with ghc -static -optl-static -optl-pthread, I get a warning: "Using dlopen in statically linked applications requires at runtime the shared libraries from the glibc version used for linking". (There are more similar warnings if I use network package). Makes sense: statically linked glibc is not really supported. The question is, how to link statically everything except glibc?

submitted by DravRorn
[link] [6 comments]
Categories: Incoming News

Type inference regression with monad-control

Haskell on Reddit - Sun, 01/17/2016 - 1:55pm

So here's a thing that's been confusing me today. I resurrected some older code and noticed that it no longer typechecks. It used to at some point, but time makes all types more ambiguous, it seems. Reducing it to the basics, I'm doing something like this:

main :: IO () main = do _ <- flip runStateT (0 :: Int) $ do control $ \run -> liftIO $ catch (putStrLn "Hello World" >> run (modify' (+ 10) >> return (Just (10 :: Int)))) (\(_ :: SomeException) -> run (modify' (+ 10) >> return Nothing)) return ()

The usual monad-control magic to tunnel my transformer stack through a IO function. Notice the two invocation of run for both the normal and failure case. This works just fine. Here's a slightly more complicated variation:

withSomething :: (MonadBaseControl IO m) => (Int -> m a) -> m (Maybe a) withSomething f = control $ \run -> liftIO $ catch (run $ Just <$> f 10) (\(_ :: SomeException) -> run $ return Nothing)

The return type here depends on the free type variables from the argument function. This no longer typechecks:

Couldn't match type ‘StM m (Maybe a)’ with ‘StM m (Maybe a0)’ NB: ‘StM’ is a type function, and may not be injective The type variable ‘a0’ is ambiguous Expected type: IO (StM m (Maybe a)) Actual type: IO (StM m (Maybe a0))

I swear I've done this exact thing all the time and it always worked. On GHC 7.8 and some older version of monad-control. Being a bit more explicit with the types and annotating the failure case which seems to trouble GHC:

withSomething :: forall a m. (MonadBaseControl IO m) => (Int -> m a) -> m (Maybe a) withSomething f = control $ \run -> liftIO $ catch (run $ Just <$> f 10) (\(_ :: SomeException) -> run $ return (Nothing :: Maybe a))

...and it works again. Hm. I don't suspect the issue is GHC 7.10, but the changelog of monad-control indicates something that might've broken it:

Switch the associated data types StT and StM to associated type synonyms. This is an API breaking change.

I don't really know what that's about but that change has certainly happened in the meantime. I can fix my problem by being a bit more explicit with my type annotations, but I'm a bit confused why it's suddenly no longer possible to just infer the types. They strike me as rather unambiguous. If anybody has a handle on what the issue is, I'd be curious to know ;-)

submitted by SirRockALot1
[link] [3 comments]
Categories: Incoming News

Is there a way to have a function that returns a random number?

Haskell on Reddit - Sun, 01/17/2016 - 12:48pm

I understand why random numbers are so wonky in Haskell. They're considered 'impure' and are thus put in the IO monad. Is there a way to write a function that will return a random number though?

submitted by Grantselrich
[link] [27 comments]
Categories: Incoming News

wren gayle romano: A week of "P"s

Planet Haskell - Sun, 01/17/2016 - 12:34pm

The next week+ I'll be in St. Petersburg Florida for PEPM, PADL, POPL, PPS, and PPAML PI (also CPP and OBT). Would've mentioned it sooner, but it's a bit of a last minute thing. I love reconnecting with old friends and meeting new folks, so feel free to come say hi. If you want to meet up for dinner or such, leave a comment with when/where to find you, or just look for the tall gal with the blue streak in her hair.



comments
Categories: Offsite Blogs

Idris compile checked printf, possible in Haskell soon? (with TypeInType coming up, etc)

Haskell on Reddit - Sun, 01/17/2016 - 11:52am

With the new TypeInType extension coming up in GHC 8.0, and a lot of work going into getting dependent type features in Haskell, I was wondering how far we are from something like this https://gist.github.com/puffnfresh/11202637, which is done in Idris (explanation of the code here https://www.youtube.com/watch?v=fVBck2Zngjo)?

A TL;DR of the link: It's a compile time checked version of printf, where the current Text.Printf gives runtime exceptions on wrong usage, the idris version is able to catch this beforehand.

submitted by Tehnix
[link] [39 comments]
Categories: Incoming News

Gabriel Gonzalez: How to contribute to the Haskell ecosystem

Planet Haskell - Sun, 01/17/2016 - 11:40am

I wanted to share a few quick ways that beginning Haskell programmers can contribute to the Haskell ecosystem. I selected these tasks according to a few criteria:

  • They are fun! These tasks showcase enjoyable tricks
  • They are easy! They straightforwardly apply existing libraries
  • They are useful! You can probably find something relevant to your project

For each task I'll give a brief end-to-end example of what a contribution might look like and link to relevant educational resources.

This post only assumes that you have the stack build tool installed, which you can get from haskellstack.com. This tool takes care of the rest of the Haskell toolchain for you so you don't need to install anything else.

Contribution #1: Write a parser for a new file format

Writing parsers in Haskell is just about the slickest thing imaginable. For example, suppose that we want to parse the PPM "plain" file format, which is specified like this [Source]:

Each PPM image consists of the following:

  1. A "magic number" for identifying the file type. A ppm image's magic number is the two characters "P3".
  2. Whitespace (blanks, TABs, CRs, LFs).
  3. A width, formatted as ASCII characters in decimal.
  4. Whitespace.
  5. A height, again in ASCII decimal.
  6. Whitespace.
  7. The maximum color value (Maxval), again in ASCII decimal. Must be less than 65536 and more than zero.
  8. A single whitespace character (usually a newline).
  9. A raster of Height rows, in order from top to bottom. Each row consists of Width pixels, in order from left to right. Each pixel is a triplet of red, green, and blue samples, in that order. Each sample is represented as an ASCII decimal number.

The equivalent Haskell parser reads almost exactly like the specification:

{-# LANGUAGE OverloadedStrings #-}

import Control.Monad (guard)
import Data.Attoparsec.Text

data PPM = PPM
{ width :: Int
, height :: Int
, maximumColorValue :: Int
, image :: [[RGB]]
} deriving (Show)

data RGB = RGB
{ red :: Int
, green :: Int
, blue :: Int
} deriving (Show)

ppm3 :: Parser PPM
ppm6 = do
"P3"
skipMany1 space
w <- decimal
skipMany1 space
h <- decimal
skipMany1 space
maxVal <- decimal
guard (maxVal < 65536)
space
let sample = do
lo <- decimal
skipMany1 space
return lo
let pixel = do
r <- sample
g <- sample
b <- sample
return (RGB r g b)

rows <- count h (count w pixel)
return (PPM w h maxVal rows)

We can try to test our parser out on the following example file:

$ cat example.ppm
P6
4 4
255
0 0 0 100 0 0 0 0 0 255 0 255
0 0 0 0 255 175 0 0 0 0 0 0
0 0 0 0 0 0 0 15 175 0 0 0
255 0 255 0 0 0 0 0 0 255 255 255

We don't even have to compile a program to test our code. We can load our code into the Haskell REPL for quick feedback on whether or not our code works:

$ stack ghci attoparsec --resolver=lts-3.14
...
Prelude> :load ppm.hs
[1 of 1] Compiling Main ( ppm.hs, interpreted )
Ok, modules loaded: Main.
*Main> txt <- Data.Text.IO.readFile "example.ppm"
*Main> parseOnly ppm3 txt
Right (PPM {width = 4, height = 4, maximumColorValue = 255,
image = [[RGB {red = 0, green = 0, blue = 0},RGB {red = 100,
green = 0, blue = 0},RGB {red = 0, green = 0, blue = 0},RGB
{red = 255, green = 0, blue = 255}],[RGB {red = 0, green =
0, blue = 0},RGB {red = 0, green = 255, blue = 175},RGB {red
= 0, green = 0, blue = 0},RGB {red = 0, green = 0, blue = 0
}],[RGB {red = 0, green = 0, blue = 0},RGB {red = 0, green =
0, blue = 0},RGB {red = 0, green = 15, blue = 175},RGB {red
= 0, green = 0, blue = 0}],[RGB {red = 255, green = 0, blue
= 255},RGB {red = 0, green = 0, blue = 0},RGB {red = 0, gre
en = 0, blue = 0},RGB {red = 255, green = 255, blue = 255}]]
})

Works like a charm!

You can very quickly get your hands dirty with Haskell by writing a parser that converts a file format you know and love into a more structured data type.

To learn more about parser combinators in Haskell, I highly recommend this "functional pearl":

... as well as this attoparsec tutorial:

To see a "long form" example of attoparsec, check out this HTTP request parser written using attoparsec:

I use "long form" in quotes because the entire code is around 60 lines long.

Contribution #2: Write a useful command-line tool

Haskell's turtle library makes it very easy to write polished command-line tools in a tiny amount of code. For example, suppose that I want to build a simple comand-line tool for managing a TODO list stored in a todo.txt file. First I just need to provide a subroutine for displaying the current list:

{-# LANGUAGE OverloadedStrings #-}

import Turtle

todoFile = "TODO.txt"

todoItem = d%": "%s

display :: IO ()
display = sh (do
(n, line) <- nl (input todoFile)
echo (format todoItem n line) )

... a subroutine for adding an item to the list:

add :: Text -> IO ()
add txt = runManaged (do
tempfile <- mktempfile "/tmp" "todo"
output tempfile (input todoFile <|> pure txt)
mv tempfile todoFile )

... and a subroutine for removing an item from the list:

remove :: Int -> IO ()
remove m = runManaged (do
tempfile <- mktempfile "/tmp" "todo"
output tempfile (do
(n, line) <- nl (input todoFile)
guard (m /= n)
return line )
mv tempfile todoFile )

... then I can just wrap them in a command line API. I create a command line parser that runs display by default if the command line is empty:

parseDisplay :: Parser (IO ())
parseDisplay = pure display

... then a command line parser for the add subcommand:

parseAdd :: Parser (IO ())
parseAdd =
fmap add
(subcommand "add" "Add a TODO item"
(argText "item" "The item to add to the TODO list") )

... and a command line parser for the remove subcommand:

parseRemove :: Parser (IO ())
parseRemove =
fmap remove
(subcommand "rm" "Remove a TODO item"
(argInt "index" "The numeric index of the TODO item to remove") )

Finally, I combine them into a single composite parser for all three subcommands:

parseCommand :: Parser (IO ())
parseCommand = parseDisplay <|> parseAdd <|> parseRemove

... and run the parser:

main = do
command <- options "A TODO list manager" parseCommand
exists <- testfile todoFile
when (not exists) (touch todoFile)
command

... and I'm done! That's the full program:

{-# LANGUAGE OverloadedStrings #-}

import Turtle

todoFile = "TODO.txt"

todoItem = d%": "%s

display :: IO ()
display = sh (do
(n, line) <- nl (input todoFile)
echo (format todoItem n line) )

add :: Text -> IO ()
add txt = runManaged (do
tempfile <- mktempfile "/tmp" "todo"
output tempfile (input todoFile <|> pure txt)
mv tempfile todoFile )

remove :: Int -> IO ()
remove m = runManaged (do
tempfile <- mktempfile "/tmp" "todo"
output tempfile (do
(n, line) <- nl (input todoFile)
guard (m /= n)
return line )
mv tempfile todoFile )

parseDisplay :: Parser (IO ())
parseDisplay = pure display

parseAdd :: Parser (IO ())
parseAdd =
fmap add
(subcommand "add" "Add a TODO item"
(argText "item" "The item to add to the TODO list") )

parseRemove :: Parser (IO ())
parseRemove =
fmap remove
(subcommand "rm" "Remove a TODO item"
(argInt "index" "The numeric index of the TODO item to remove") )

parseCommand :: Parser (IO ())
parseCommand = parseDisplay <|> parseAdd <|> parseRemove

main = do
command <- options "A TODO list manager" parseCommand
exists <- testfile todoFile
when (not exists) (touch todoFile)
command

We can compile that program into an native binary on any platform (i.e. Windows, OS X, or Linux) with a fast startup time:

$ stack build turtle --resolver=lts-3.14
$ stack ghc --resolver=lts-3.14 -- -O2 todo.hs

... and verify that the program works:

$ ./todo add "Brush my teeth"
$ ./todo add "Shampoo my hamster"
$ ./todo
0: Brush my teeth
1: Shampoo my hamster
$ ./todo rm 0
$ ./todo
0: Shampoo my hamster

The program also auto-generates the usage and help information:

$ ./todo --help
A TODO list manager

Usage: todo ([add] | [rm])

Available options:
-h,--help Show this help text

Available commands:
add
rm
$ ./todo add
Usage: todo add ITEM
$ ./todo rm
Usage: todo rm INDEX

Amazingly, you can delete all the type signatures from the above program and the program will still compile. Try it! Haskell's type inference and fast type-checking algorithm makes it feel very much like a scripting language. The combination of type inference, fast startup time, and polished command line parsing makes Haskell an excellent choice for writing command-line utilities.

You can learn more about scripting in Haskell by reading the turtle tutorial, written for people who have no prior background in Haskell programming:

Contribution #3: Client bindings to a web API

Haskell's servant library lets you write very clean and satisfying bindings to a web API. For example, suppose that I want to define a Haskell client to to the JSONPlaceholder test API. We'll use two example endpoints that the API provides.

A GET request against the /posts endpoint returns a list of fake posts:

[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat ..."
"body": "quia et suscipit\nsuscipit ..."
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi ..."
},
...

... and a POST request against the same endpoint accepts a list of posts and returns them back as the response.

To write a client binding to this API, we just need to define a record representing APost:

data APost = APost
{ userId :: Int
, id :: Int
, title :: Text
, body :: Text
} deriving (Show, Generic, FromJSON, ToJSON)

The last line instructs the Haskell compiler to auto-derive conversion functions between APost and JSON.

Now we just encode the REST API as a type:

-- We can `GET` a list of posts from the `/posts` endpoint
type GetPosts = "posts" :> Get '[JSON] [APost]

-- We can `POST` a list of posts to the `/posts` endpoint
-- using the request body and get a list of posts back as
-- the response
type PutPosts = ReqBody '[JSON] [APost] :> "posts" :> Post '[JSON] [APost]

type API = GetPosts :<|> PutPosts

... and then the compiler will "automagically" generate API bindings:

getPosts :<|> putPosts =
client (Proxy :: Proxy API) (BaseUrl Http "jsonplaceholder.typicode.com" 80)

Now anybody can use our code to GET or POST lists of posts. We can also quickly test out our code within the Haskell REPL to verify that everything works:

$ stack ghci servant-server servant-client --resolver=lts-3.14
ghci> :load client.hs
[1 of 1] Compiling Main ( httpbin.hs, interpreted )
Ok, modules loaded: Main.
*Main> import Control.Monad.Trans.Either as Either
*Main Either> -- Perform a `GET` request against the `/posts` endpoint
*Main Either> runEitherT getPosts
Right [APost {userId = 1, id = 1, title = "sunt aut facere ...
*Main Either> -- Perform a `POST` request against the `/posts` endpoint
*Main Either> runEitherT (putPosts [APost 1 1 "foo" "bar"])
Right [APost {userId = 1, id = 1, title = "foo", body = "bar"}]

Here's the full code with all the extensions and imports that enable this magic:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}

import Data.Aeson (FromJSON, ToJSON)
import Data.Text (Text)
import GHC.Generics (Generic)
import Servant
import Servant.Client

data APost = APost
{ userId :: Int
, id :: Int
, title :: Text
, body :: Text
} deriving (Show, Generic, FromJSON, ToJSON)

type GetPosts = "posts" :> Get '[JSON] [APost]
type PutPosts = ReqBody '[JSON] [APost] :> "posts" :> Post '[JSON] [APost]
type API = GetPosts :<|> PutPosts

getPosts :<|> putPosts =
client (Proxy :: Proxy API) (BaseUrl Http "jsonplaceholder.typicode.com" 80)

To learn more about how this works, check out the servant tutorial here:

Note that servant is both a client and server library so everything you learn about auto-generating client side bindings can be reused to auto-generate a server, too!

To see a more long-form example of bindings to the Google Translate API, check out this code:

Conclusion

Suppose that you write up some useful code and you wonder: "What's next? How do I make this code available to others?". You can learn more by reading the stack user guide which contains complete step-by-step instructions for authoring a new Haskell project, including beginning from a pre-existing project template:

Categories: Offsite Blogs