2

比如说,我在单独的 DB.hs 文件中有一个随机 DB 函数。像这样的东西:

savePerson :: Person -> IO ()
  savePerson p = do
  c <- connect
  run c "INSERT INTO persons (name, age) \
        \VALUES (?, ?)"
        [toSql (personName p), toSql (personAge p)]
  commit c
  disconnect c
  return ()

现在,如果我导入 DB.hs,如何在 Site.hs 中的处理程序中执行这些函数?

如果我像这样简单地将它粘贴在我的处理程序中(这只是一个示例):

insertPerson = do
  par <- getPostParams
  let p = toPerson par
  savePerson p
  return ()
  where
    toPerson m =
      Person {personName = head (m ! (B.pack "name"))
             ,personAge  = read (B.unpack (head (m ! (B.pack "age")))) :: Int
             }

这不起作用。我不希望处理程序返回任何东西,我只希望它保存 Person 而不返回/渲染任何东西。

正确的做法是什么?

谢谢。

4

1 回答 1

1

您的问题似乎是您不了解单位类型和值的含义。

单位类型是一种特殊的内置类型,称为“()”,它只有一个值,也称为“()”。

因此,例如,我可以创建一个包含 4 个单元的列表,其类型为“单元列表”。

fourUnits :: [()]
fourUnits = [(), (), (), ()]

单位类型用于我们不希望有任何其他信息的地方。所以从技术上讲,类型“IO()”是给出单位值的 IO 动作的类型。

“do”子句取消了“>>=”调用链。">>=" 有类型

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

换句话说,“do”子句的类型是其最后一个动作返回的类型。

所以你说的地方

savePerson p
return ()

“return ()”是虚假的,因为它与“savePerson p”具有完全相同的类型。

请记住,“返回”与控制流无关:它只是一个具有类型的函数

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

最好将其称为“包装”或“注入”或类似的名称,以避免这种混淆。

于 2012-03-25T12:53:41.723 回答