我正在使用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&lt; - look“personId”
在阅读有关类似问题的问题后(例如this one),我认为我必须在某处包含HasRqData
约束,但我无法了解地点和方式。
答案 0 :(得分:1)
正如您可能已经猜到的那样,monad也是一个问题。 happstack
(HasRqData
等)中有handful个,因此您可能会认为这是一个复杂的案例。
让我们从无辜的 look
函数开始。
look :: (Functor m, Monad m, HasRqData m) => String -> m String
实际上,存在一个非平凡的约束HasRqData
。让我们问问自己:what monads HaveRqData? (碰巧IO
没有!)
class HasRqData m where
...
Instances
HasRqData RqData
(MonadIO m, MonadPlus m) => HasRqData (ServerPartT m)
...
其他实例是前两个实例的衍生物,因此,看起来我们必须首先考虑这两个选项。
RqData
效果有限 - 您只能look
及其衍生物,从手头的请求中提取信息。因为我们还希望有其他效果 - 例如查询数据库 - 这对我们来说还不够。ServerPartT m
是同一old friend of ours,ServerPart ≡ ServerPartT IO
的一般形式。碰巧它也是HasRqData
。这不是巧合,而是happstack
设计的含义 - 看起来作者的意思是我们在任何地方使用这个单一的monad,除非我们需要特定的粒度。所以,让我们试一试。
myFunc :: ServerPart String
myFunc = do r <- look "personId"
return undefined
编译。
现在,我们甚至不需要在myFunc
中举起handlers
- 我们previous predicament解决了问题。我们需要通过我们之前讨论过的jar logic提升对数据库的访问权。
我相信你可以自己计算细节。在任何情况下,让我知道它是如何工作的!