不同的读者行为

时间:2017-09-02 21:03:16

标签: haskell continuations reader-monad

我正在围绕Warp服务器编写一个包装器,用户可以在其中指定路由和处理程序来创建Web服务器。我决定尝试使用Continuation Monads来允许处理程序在路由匹配时使用continuation退出。 以下是我开始使用的类型和定义:

import Control.Monad.Cont
import Control.Monad.Reader
import qualified Network.Wai as W
import qualified Data.Text as T

type App r a = ContT r (ReaderT W.Request IO) a
type Handler a = ReaderT W.Request IO a
type Respond = ((Status, T.Text) -> App (Status, T.Text) ())

route :: T.Text -> Handler (Status, T.Text) -> Respond -> App (Status, T.Text) ()
route routePath handler respond = do
  liftIO $ print $ "Checking" `T.append` routePath
  pth <- path
  when (routePath == pth) $ do
    req <- ask
    response <- liftIO $ runReaderT handler req
    respond response

app是路由的集合,每个路由从Reader环境读取当前的continuation;我原来是这样写的:

hello :: Handler (Status, T.Text)
hello = return (ok200, "Hello World!")

goodbye :: Handler (Status, T.Text)
goodbye = return (ok200, "Goodbye World!")

app :: Respond -> App (Status, T.Text) ()
app = do
  route "/hello" hello
  route "/goodbye" goodbye

奇怪的是,这似乎不起作用,它只打印&#34;检查/再见&#34 ;;但是,如果我们改为以下一种形式编写阅读器,它就能正常工作,据我所知,这两个定义应该是等价的;但显然我错过了一些东西:

app :: Respond -> App (Status, T.Text) ()
app resp = do
  route "/hello" hello resp
  route "/goodbye" goodbye resp

有什么方法可以使用原始应用定义获得正确的行为?读者Monad是否有某种方式以某种方式搞乱延续?

我怀疑读者的monad定义在某种程度上打断了计算的顺序;但我不清楚如何:

instance Monad ((->) r) where
    f >>= k = \ r -> k (f r) r

谢谢!

0 个答案:

没有答案