做块解析类型

Do block resolve types

我最近才开始 Haskell 编码,并且开始使用 do block。我来自 Scala 世界,在读了一本书和一些博客后,我发现 do block 是我们理解的灵感来源。但我仍然在为每个函数作为输入传递的参数而苦苦挣扎 - >输出

在我的代码中,我使用 scotty http 服务器库来获取请求,并且我试图在 mySQL.

中保留该请求

但是在这一行中,我尝试从 Maybe 中获取值以发送到另一个要持久化的函数

user <- (fmap (\user -> insertUser user) maybeUser)

它永远不会编译,因为函数没有return预期的类型

ActionT Text IO (Maybe User)

但是

IO User

这是我的洞计划

createUser :: ActionM ()
createUser =  do maybeUser <- getUserParam
                          -- Persist the user
                          _ <- persistUser
                          json maybeUser

getUserParam :: ActionT Text IO (Maybe User)
getUserParam = do requestBody <- body
                  return (decode requestBody)

persistUser :: Maybe User -> ActionT Text IO (Maybe User)
persistUser _maybeUser = let maybeUser = _maybeUser in do
                           user <- maybeUser
                           user <- (fmap (\user -> insertUser user) maybeUser)
                           return maybeUser

insertUser :: User -> IO User
insertUser _user = let user = _user in do
    conn <- createConnection
    status <- execute conn insertUserQuery [MySQLInt32 (intToInt32 $ getUserId user), MySQLText "hello_haskell_world"]
    return user

让我们考虑以下函数:

persistUser :: Maybe User -> ActionT Text IO (Maybe User)

类型Maybe User的值作为参数传递,我们需要将此用户插入数据库。为此,我们可以使用 (<$>)(或 fmap)函数作为:

insertUser <$> maybeUser

结果类型为:Maybe (IO User)。现在我们需要lift这个类型以某种方式ActionT Text IO (Maybe User)

Web.Scotty.Trans 有一个 liftAndCatchIO function (also available in Web.Scotty module), which mostly does what we need, but it accepts IO a as an argument, so we need to "swap" Maybe and IO. Let's find a function for this. So sequence 可以满足我们的需要。

因此,我们有以下 persistUser 函数的实现:

persistUser maybeUser =
    liftAndCatchIO $ sequence $ insertUser <$> maybeUser