请原谅我的无知,但是,有没有办法调用Handler ()
从只返回的方法返回的方法IO ()
例如考虑这两种方法
onReceiveMessage :: IO ()
onReceiveMessage = do
_ <- putStrLn "Received Message"
_ <- doSomething
return ()
doSomething :: Handler ()
doSomething = return ()
这似乎无法编译。我试图以几种不同的方式编译它,但都是一致的。我相信这一定是可能的,但只是不知道如何。
任何想法?
更新
扩展上一个示例,假设我有另一个函数,它接收上一个函数的值并返回 IO ()。那也行不通。
onReceiveMessage :: IO ()
onReceiveMessage =
doSomething >>= doSomethingElse
doSomething :: Handler MessageStatus
doSomething = return MessageStatus.Success
doSomethingElse :: MessageStatus -> IO ()
doSomethingElse _ = return ()
这似乎也不起作用。可以使用 liftIO 函数从 Handler 调用 IO 操作,例如下面的函数可以编译并正常工作。它从返回 Handler MessageStatus 的函数调用 IO () 操作。这是使用 liftIO 函数实现的。
doSomething' :: Handler MessageStatus
doSomething' = (liftIO $ putStrLn "hello world") >> return MessageStatus.Success
我们有类似从 IO 调用 Handler 操作的东西吗?
更新 2
提供更多上下文并解释我是如何解决问题的。
我试图在 Yesod 应用程序中 使用amqp包来收听 RabbitMQ 。
- 当我收到一条消息时,会调用一个回调。
- 回调需要有签名
(Message, Envelope) -> IO ()
。 - 从回调中我需要执行一些 SQL。
- 现在我不想编写代码来解析配置文件并管理我自己的连接池。
- 因此,我想将我的代码与 Yesod 提供的名为
runDB
. - 但是由于它的返回值被包装在
Handler
我无法从消息回调中调用它。
我最终做的是
- 获取
App
(Foundation
) 对象,同时将其构建在 中Application.hs
并将其传递给我的代码。 - 然后为消息回调创建一个柯里化函数
- 在 curried 函数中,我保留了 Yesod 已经构建的配置对象,同时构建了基础
- 在我弄清楚这一点之后很轻松,使用配置对象我可以从 settings.yml 中读取我的所有设置,甚至保持一个并行连接池。
- 此连接池将用于从消息回调中触发我的所有查询。
- 不仅如此,而且因为我使用了这种方法,我可以免费获得日志记录,并且无需编写任何代码就可以在控制台上查看所有查询。
总的来说,我觉得我可能有复杂的事情,但目前我不知道有什么更好的方法。如果有人有更好的主意,我很想听听。