Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smoother type annotation in bind chain

Tags:

haskell

So I have this working example (Snap + Postgres):

listBooks :: AppHandler ()
listBooks = do
  results <- query_ "select * from books"
  writeJSON $ (results :: [Book])

As an exercise I'm trying to rewrite this with >>= operator, but the need to annotate type kills the aesthetics. I couldn't come up with anything better than:

query_ "select * from books" >>= return.(\x -> x :: [Book]) >>= writeJSON

Is there any other "smoother" way? (preferably without specifying the wrapping monad type)

like image 533
forker Avatar asked Dec 15 '22 12:12

forker


2 Answers

You can shorten it slightly to

query_ "select * from books" >>= writeJSON . (\x -> x :: [Book])

Other than that, not yet, although there are plans to implement a GHC extension for a shortcut syntax

(:: [Book]) = (\x -> x :: [Book])

Looking at @duplode's link it seems like the code for it started getting written 3 days ago, so should be in the next GHC release.

like image 154
Ørjan Johansen Avatar answered Dec 24 '22 09:12

Ørjan Johansen


If you turn on PartialTypeSignatures, you can write:

query_ "select * from books" >>= (writeJSON :: [Book] -> _)

One could also spell this as a constraint on query_; e.g. in your do version, it would be:

listBooks :: AppHandler ()
listBooks = do
  results <- query_ "select * from books" :: _ [Book]
  writeJSON results

In future versions of GHC, there will also be visible type application. Assuming that writeJSON or query_ has a suitable type declaration, you would then be able to write one of these:

query_ @[Book] "select * from books" >>= writeJSON
query_ "select * from books" >>= writeJSON @[Book]

Finally, if you are averse to type annotations but okay with term annotations, you could write

query_ "select * from books" >>= asAppliedTo [Book{}] writeJSON

where Book is a hypothetical constructor for the Book type (the point being that [Book{}], while a nonsense value, has a monomorphic type). I seem to recall that asAppliedTo is a standard thing, but a quick hoogle doesn't reveal it; in any case, it is implemented similar to this:

asAppliedTo :: arg -> (arg -> result) -> (arg -> result)
asAppliedTo _ = id
like image 31
Daniel Wagner Avatar answered Dec 24 '22 10:12

Daniel Wagner