在Servant

时间:2016-02-11 13:37:53

标签: haskell servant

我正在尝试使用telegram-api构建Telegram机器人。到目前为止,我没有遇到任何问题,因为我可以阅读测试以了解事情是如何工作的,但是在使用Servant构建webhook端点时遇到了很多麻烦。总的想法是,当我从webhook收到Update时,我会发回回复。

问题在于我的postWebhook代码,它希望收到Message,但会收到IO Message。我认为这是因为Servant不希望我在该函数内部发出请求,因为我的类型为EitherT ServantError IO (IO Message)(部分由BotHandler应用),而实际应该是EitherT ServantError IO Message。< / p>

我还在学习Haskell,但我知道我不得不从IO monad中获取消息?更新BotAPI以返回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代码。提前谢谢你:)

1 个答案:

答案 0 :(得分:5)

您的错误发生在

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,变形金刚......,在这些复杂的例子之前,你是勇敢的! :)