Reputation: 6495
I'm getting to grips with writing an API in Haskell using Scotty. My files are provided below. My questions are:
In the routes definition, I'm extracting from liftIO whatsTheTime in a do block. This works, but it seems verbose. Is there a nicer syntax?
In the whatsTheTime definition, I'm needing to do fromString. I'd have thought OverloadedString would take care of that, but that's not the case. I'd really appreciate it if somebody pointed out why it doesn't work without fromString.
In a stack project, if I need a directive like OverloadedStrings, do I need to include it every file that needs it, or just at the top of the main entrypoint?
Api.hs:
{-# LANGUAGE OverloadedStrings #-}
module Api
( whatsTheTime
) where
import Data.Time (getCurrentTime)
import Web.Scotty
import Data.String
whatsTheTime :: IO (ActionM ())
whatsTheTime = do
time <- getCurrentTime
return $ text $ fromString ("The time is now " ++ show time)
Main.hs:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module Main where
import Api
import Web.Scotty
import Control.Monad.IO.Class
routes = do
get "/" $ do
res <- liftIO whatsTheTime
res
main :: IO ()
main = do
putStrLn "Starting server..."
scotty 3000 routes
Upvotes: 3
Views: 980
Reputation: 55049
(1) This:
do
res <- liftIO whatsTheTime
res
Desugars to this:
liftIO whatsTheTime >>= \ res -> res
If you look at the type of \ m -> m >>= id
:
(Monad m) => m (m a) -> m a
That’s exactly the type of join
(Hoogle), so you can use:
get "/" $ join $ liftIO whatsTheTime
join
is a common idiom for “execute this action which returns an action, and also execute the returned action”.
(2) OverloadedStrings
is for overloading of string literals. You have an overloaded literal "The time is now "
, but you constrain it to be of type String
by using it as an operand of (++)
with a String
(the result of show time
). You can pack the result of show time
as a Text
instead using fromString
or Data.Text.pack
:
import Data.Monoid ((<>))
import qualified Data.Text as Text
-- ...
return $ text $ "The time is now " <> Text.pack (show time)
(3) LANGUAGE
pragmas operate per file; as @mgsloan notes, you can add OverloadedStrings
to the default-extensions:
field of your library or executable in your .cabal
file.
Upvotes: 3