在 Servant 的 API 端点内发出请求
Making a request inside an API endpoint in Servant
我正在尝试使用 telegram-api. I haven't had an issues with that so far since I could read the tests to understand how things worked, but I've had a lot of trouble when it comes to building a webhook endpoint with Servant 构建 Telegram 机器人。总体思路是,当我从 webhook 收到 Update
时,我会发回回复。
问题与我的 postWebhook
代码有关,它期望收到 Message
但收到的却是 IO Message
。我认为这是因为 Servant 不希望我在该函数内发出请求,因为我有类型 EitherT ServantError IO (IO Message)
(部分由 BotHandler
应用),而实际上它应该是 EitherT ServantError IO Message
。
我还在学习 Haskell 但我知道我必须以某种方式从 IO monad 中获取消息?将 BotAPI
更新为 return a Post '[JSON] (IO Message)
给了我这个:No instance for (Foldable IO) arising from a use of ‘serve’
,这超出了我的初学者知识范围,我可以看到摆弄类型只是解决了同样的问题到代码的不同部分。我只是不知道如何解决它。
以下是删除了敏感字符串的代码:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module Main where
import Control.Monad
import Control.Monad.Trans.Either
import Data.Proxy
import Data.Text (Text, pack)
import Network.Wai.Handler.Warp
import Servant
import Web.Telegram.API.Bot
reply :: Token -> Message -> Text -> IO Message
reply token msg response = do
Right MessageResponse { message_result = m } <-
sendMessage token $ SendMessageRequest chatId response (Just Markdown) Nothing Nothing Nothing
return m
where chatId = pack . show $ chat_id (chat msg)
type BotAPI = "webhook" :> ReqBody '[JSON] Update :> Post '[JSON] Message
type BotHandler a = EitherT ServantErr IO a
botApi :: Proxy BotAPI
botApi = Proxy
initWebhook :: Token -> IO Bool
initWebhook token = do
Right SetWebhookResponse { webhook_result = w } <-
setWebhook token $ Just "https://example.com/webhook"
return w
postWebhook :: Token -> Update -> BotHandler (IO Message)
postWebhook token update = case message update of
Just msg -> return $ reply token msg "Testing!"
Nothing -> left err400
server :: Token -> Server BotAPI
server = postWebhook
main :: IO ()
main = do
initWebhook token
run port $ serve botApi (server token)
where token = Token "<token>"
port = 8080
对于可能不理想的 Haskell 代码表示歉意。提前谢谢你:)
你的错误在
Just msg → return $ reply token msg "Testing!"
你在
EitherT ServantErr IO Message
monad 但 reply
有类型
reply :: Token → Message → Text → IO Message
然后简单地 lift
那个 IO
动作到你的 monad 中,它起作用了
postWebhook :: Token → Update → BotHandler Message
postWebhook token update = case message update of
Just msg → lift $ reply token msg "Testing!"
Nothing → left err400
(对我来说解释这里涉及的所有事情并不容易)我认为你应该在这些复杂的例子之前多练习一下 monads,transformers,......但你很勇敢! :)
我正在尝试使用 telegram-api. I haven't had an issues with that so far since I could read the tests to understand how things worked, but I've had a lot of trouble when it comes to building a webhook endpoint with Servant 构建 Telegram 机器人。总体思路是,当我从 webhook 收到 Update
时,我会发回回复。
问题与我的 postWebhook
代码有关,它期望收到 Message
但收到的却是 IO Message
。我认为这是因为 Servant 不希望我在该函数内发出请求,因为我有类型 EitherT ServantError IO (IO Message)
(部分由 BotHandler
应用),而实际上它应该是 EitherT ServantError IO Message
。
我还在学习 Haskell 但我知道我必须以某种方式从 IO monad 中获取消息?将 BotAPI
更新为 return a Post '[JSON] (IO Message)
给了我这个:No instance for (Foldable IO) arising from a use of ‘serve’
,这超出了我的初学者知识范围,我可以看到摆弄类型只是解决了同样的问题到代码的不同部分。我只是不知道如何解决它。
以下是删除了敏感字符串的代码:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module Main where
import Control.Monad
import Control.Monad.Trans.Either
import Data.Proxy
import Data.Text (Text, pack)
import Network.Wai.Handler.Warp
import Servant
import Web.Telegram.API.Bot
reply :: Token -> Message -> Text -> IO Message
reply token msg response = do
Right MessageResponse { message_result = m } <-
sendMessage token $ SendMessageRequest chatId response (Just Markdown) Nothing Nothing Nothing
return m
where chatId = pack . show $ chat_id (chat msg)
type BotAPI = "webhook" :> ReqBody '[JSON] Update :> Post '[JSON] Message
type BotHandler a = EitherT ServantErr IO a
botApi :: Proxy BotAPI
botApi = Proxy
initWebhook :: Token -> IO Bool
initWebhook token = do
Right SetWebhookResponse { webhook_result = w } <-
setWebhook token $ Just "https://example.com/webhook"
return w
postWebhook :: Token -> Update -> BotHandler (IO Message)
postWebhook token update = case message update of
Just msg -> return $ reply token msg "Testing!"
Nothing -> left err400
server :: Token -> Server BotAPI
server = postWebhook
main :: IO ()
main = do
initWebhook token
run port $ serve botApi (server token)
where token = Token "<token>"
port = 8080
对于可能不理想的 Haskell 代码表示歉意。提前谢谢你:)
你的错误在
Just msg → return $ reply token msg "Testing!"
你在
EitherT ServantErr IO Message
monad 但 reply
有类型
reply :: Token → Message → Text → IO Message
然后简单地 lift
那个 IO
动作到你的 monad 中,它起作用了
postWebhook :: Token → Update → BotHandler Message
postWebhook token update = case message update of
Just msg → lift $ reply token msg "Testing!"
Nothing → left err400
(对我来说解释这里涉及的所有事情并不容易)我认为你应该在这些复杂的例子之前多练习一下 monads,transformers,......但你很勇敢! :)