简体   繁体   English

LiftIO,执行块和语法

[英]LiftIO, do block, and syntax

I'm getting to grips with writing an API in Haskell using Scotty. 我正在努力使用Scotty在Haskell中编写API。 My files are provided below. 我的文件在下面提供。 My questions are: 我的问题是:

  1. In the routes definition, I'm extracting from liftIO whatsTheTime in a do block. 在路由定义中,我从liftIO中的do块中提取whatsTheTime。 This works, but it seems verbose. 这可行,但似乎很冗长。 Is there a nicer syntax? 有更好的语法吗?

  2. In the whatsTheTime definition, I'm needing to do fromString. 在whatsTheTime定义中,我需要执行fromString。 I'd have thought OverloadedString would take care of that, but that's not the case. 我以为OverloadedString会解决这个问题,但事实并非如此。 I'd really appreciate it if somebody pointed out why it doesn't work without fromString. 如果有人指出为什么没有fromString不能使用它,我将非常感激。

  3. 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? 在堆栈项目中,如果我需要诸如OverloadedStrings之类的指令,是否需要在每个需要它的文件中都包含它,或者仅将其包含在主入口点的顶部?

Api.hs: 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: 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

(1) This: (1):

do
  res <- liftIO whatsTheTime
  res

Desugars to this: 糖到此:

liftIO whatsTheTime >>= \ res -> res

If you look at the type of \\ m -> m >>= id : 如果您查看\\ m -> m >>= id

(Monad m) => m (m a) -> m a

That's exactly the type of join ( Hoogle ), so you can use: 这正是类型joinHoogle ),所以你可以使用:

get "/" $ join $ liftIO whatsTheTime

join is a common idiom for “execute this action which returns an action, and also execute the returned action”. join是“执行返回一个动作并执行返回的动作的该动作”的常见用法。

(2) OverloadedStrings is for overloading of string literals . (2) OverloadedStrings用于字符串文字的重载。 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 ). 你有一个重载的文字"The time is now " ,但你限制它是类型的String ,把它当做一个操作数(++)String (的结果show time )。 You can pack the result of show time as a Text instead using fromString or Data.Text.pack : 您可以使用fromStringData.Text.packshow time的结果打包为Text

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; (3) LANGUAGE Pragma按文件运行; as @mgsloan notes, you can add OverloadedStrings to the default-extensions: field of your library or executable in your .cabal file. 如@mgsloan所述,您可以将OverloadedStrings添加到库或.cabal文件中的可执行文件的default-extensions:字段中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM