1

我正在使用 Happstack 从 HTTP 请求中接收一些参数,然后将这些参数传递给一个函数,该函数将从数据库中检索数据并在 HTTP 响应中返回这些数据,如下所示:

myFunc :: IO String
myFunc = do r <- look "personId"
            conn <- connectODBC "... my connection string ...";
            vals <- quickQuery conn ("SELECT Name FROM Person where Id = ?") [(toSql r)];
            return (processData vals)

handlers :: ServerPartT IO Response
handlers = do
       x <- liftIO (myFunc);
       decodeBody (defaultBodyPolicy "/tmp/" 0 1000 1000)
       msum [ 
              dir "getData" $ ok $ toResponse x
            , ... other handlers ...
            ]

mainFunc = simpleHTTP nullConf handlers

但是当我构建上面的代码时,我得到以下错误:

没有使用 `look' 产生的 (HasRqData IO) 实例在 'do' 块的 stmt 中:r <-look "personId"

在阅读了关于类似问题的问题(比如这个)之后,我认为我必须在HasRqData某处包含约束,但我无法了解在哪里以及如何。

4

1 回答 1

1

正如您可能已经猜到的那样,这对于 monad 来说也是一个问题。在(等)中有几个,因此您可能会认为这是一个复杂的案例。happstackHasRqData

让我们从看似无辜的 look功能开始。

look :: (Functor m, Monad m, HasRqData m) => String -> m String

确实,有一个非平凡的约束HasRqData。让我们问问自己:什么单子HaveRqData?(碰巧IO没有!)

class HasRqData m where
...

Instances
    HasRqData RqData         
    (MonadIO m, MonadPlus m) => HasRqData (ServerPartT m)
    ...

其他实例是前两个的派生,因此,看起来我们必须首先考虑这两个选项。

  • RqData效果有限——您只能从手头的look请求中提取信息及其衍生品。由于我们还想产生其他效果——例如查询数据库——这对我们来说还不够。
  • ServerPartT m是我们同一个老朋友的一般形式,ServerPart ≡ ServerPartT IO。碰巧它也HasRqData。这不是巧合,而是设计的暗示happstack——看起来作者的意思是我们要在任何地方使用这个单一的 monad,除非我们需要特定的粒度。所以,让我们试一试。

 

myFunc :: ServerPart String
myFunc = do r <- look "personId"
            return undefined

这编译。

现在,我们甚至不需要采取行动myFunc——handlers我们之前的困境自己解决了。不过,我们需要通过我们之前讨论的相同jar 逻辑来提升对数据库的访问权限。

我相信你可以自己弄清楚细节。无论如何,让我知道结果如何!

于 2018-02-18T06:06:06.910 回答