haskell中的后端服务currenttime(json)



我想用haskell编写一个简单的Web服务器,它提供当前时间。时间应该以json格式返回。

以下是我目前所拥有的:

{-# LANGUAGE DeriveDataTypeable #-}
import Happstack.Server
import Text.JSON.Generic
import Data.Time
import System.IO.Unsafe
data TimeStr = TimeStr {time :: String} deriving (Data, Typeable)
main = simpleHTTP nullConf $ ok $ toResponse $ encodeJSON (TimeStr $ show (unsafePerformIO getCurrentTime)) 

我知道应该避免unsafePerformIO,但我还找不到更好的解决方案。也许这就是问题所在?我对单子有一个非常基本的理解。

结果如下:

{"time":"2014-10-16 16:11:38.834251 UTC"}

问题是,当我刷新localhost:8000时,时间不会改变。有什么记忆在进行吗?

unsafePerformIO :: IO a -> a

这是IO monad的"后门",允许随时执行IO计算。为了安全起见,IO计算应该没有副作用,并且与其环境无关

getCurrentTime依赖于它的环境,所以unsafePerformIO而不是的选择。然而,给定MonadIO,我们可以使用liftIO将动作提升到适当的monad中。让我们看看类型,找出我们可以将其插入的位置:

-- http://hackage.haskell.org/package/happstack-server-7.3.9/docs/Happstack-Server-SimpleHTTP.html
simpleHTTP :: ToMessage a => Conf -> ServerPartT IO a -> IO () 

ServerPartTMonadIO的一个实例,所以我们可以把它插在这里。让我们检查ok:

ok :: FilterMonad Response m => a -> m a 
--                       nope: ^^^

因此,在准备响应之前,我们确实需要了解当前时间。毕竟,这是有道理的:当您创建响应时,所有繁重的工作都已经完成,您知道可以使用什么响应代码,并且不需要检查数据库中是否存在文件或条目。毕竟,你本来打算发送一个200 OK的,对吧?

这给我们留下了以下解决方案:

{-# LANGUAGE DeriveDataTypeable #-}
import Happstack.Server
import Text.JSON.Generic
import Data.Time
import System.IO.Unsafe
import Control.Monad.IO.Class (liftIO)
data TimeStr = TimeStr {time :: String} deriving (Data, Typeable)
main = simpleHTTP nullConf $ do
           currentTime <- liftIO getCurrentTime
           ok $ toResponse $ encodeJSON (TimeStr $ show currentTime)

经验教训

  1. 不要使用unsafePerformIO
  2. 不要使用unsafePerformIO,除非您真的确定自己在做什么
  3. 如果要在MonadIO的实例中使用IO操作,请使用liftIO

相关内容

  • 没有找到相关文章

最新更新