应用类型

data App = App
    { _heist       :: Snaplet (Heist App)
    , _session     :: Snaplet SessionManager
    }

初始化器

...
addRoutes [ ("/ss", companyHandler)
          , ("", heistServe)
          ]
...

处理程序

companyHandler :: Handler b v ()
companyHandler = method GET getter <|> method POST setter
  where
    getter = do
        value <- getFromSession "name"
        writeText $ fromMaybe "nothing" value
    setter = do
        mname <- getParam "name"
        setInSession "name" (convert mname)
        getter
    convert = T.pack . B.unpack . (fromMaybe "nothing")

heistServe类型为Handler b (Heist b) ()

类型错误:

src/Tutorial.hs:50:52:
    Couldn't match type `v' with `SessionManager'
      `v' is a rigid type variable bound by
          the type signature for companyHandler :: Handler b v ()
          at src/Tutorial.hs:50:1
    Expected type: Handler b v ()
       Actual type: Handler b SessionManager ()
    In the second argument of `method', namely `setter'
    In the second argument of `(<|>)', namely `method POST setter'

===============>>#1 票数:3 已采纳

您必须先将SessionManager绑定到处理程序的上下文,然后才能使用对其进行操作的函数。 这完成了:

withTop session $ setInSession "name" (convert mname)
-- Where session is the generated lens for your snaplet

如果您还想在之后提交会话(因为您更改了会话而不是只读取变量),则需要:

withSession . withTop session $ ...

如果将以下代码添加到主应用程序的snaplet初始化代码中,则根本不必担心提交会话,因为它是自动完成的:

wrapHandlers withSession

===============>>#2 票数:0

解决问题的一种方法是使用以下行:

companyHandler = with session $ method GET getter <|> method POST setter

我觉得有用的另一件事是将类型签名专门化到我的应用程序。 在这种情况下,新的类型签名将是:

companyHandler :: Handler App App ()

在大多数情况下,您不会编写可在多个应用程序之间重用的通用代码,因此此处的少量通用性并不会伤害您。 通常,拥有更具体的类型签名会使错误消息更容易被破译,这对于代码编译很有帮助。 即使我正在编写应该在所有应用程序/快照中都是通用的代码,有时我仍然觉得从更具体的类型开始然后在我使其工作之后进行概括是有帮助的。

dflemstr关于withSession的说法是正确的。 我通常更倾向于对所有内容执行withSession而不是将其置于setInSession的调用上,但是您应该做适合您的应用程序的任何事情。

  ask by wenlong translate from so

未解决问题?本站智能推荐:

1回复

Haskell,Snap:简单的snaplet结构。 我们什么时候使用snaplet和库?

我想了解简单的snaplet结构。 另外,我什么时候需要制作一个snaplet和一个简单的侧库? 如果我确实需要一个如何从库中取出它? 例如,我有一堆数据库函数,我在其中包装我的SQL代码,如下所示。 每个函数都会启动一个新连接并在提交后关闭连接。 我想制作一个snaplet
1回复

如何在snaplet中使用Network.WebSockets.Snap?

能够从snaplet内部使用Network.WebSockets模块会很好,但我无法弄清楚如何实际执行它。 使用来自Network.WebSockets.Snap的runWebSocketsSnap :: MonadSnap m => ServerApp -> m ()函数,很
1回复

如何使用Snap的MysqlSimple snaplet连接到MySQL

Snap Framework提供了有关如何使用snaplet编写Web应用程序的教程。 存在一个用于连接到MySQL的Snaplet Snap.Snaplets.MysqlSimple ,它依赖于数据库Database.MySQL.Simple ,并且看起来该Snaplet主要是用于保持隐式连
1回复

如何结合PostgreSQL的snaplet和websockets?

以下代码尝试结合两个单独工作的示例: 第24天(2012年)的第19天 ,例如ws示例,但我拿走了与websocket相关的几乎所有内容,以得到一个小示例。 请在下面找到代码。 msgHandler由helloDb ,它将获取包含数据库连接的快照,并将其传递给msgHandler
1回复

Snaplet中的静态文件

我想从Snap框架中的Snaplet提供一些静态文件。 我怎么做? 文档不完全清楚。 我知道如何添加路线和东西,但我遇到两个问题: 我需要传递给serveDirectory以从snaplet目录提供文件? 我如何在我的snaplet的Heist模板中引用这些静态文件?
1回复

initPersistent的快照持久性问题

我是Haskell的初学者,尝试使用snaplet-persistent。 试图按照文档进行操作,但无法正常工作,出现了以下问题: 从github运行snaplet-persistent。
1回复

如何制作nicEditor snaplet? (几个问题)

下面的示例定义了一个将nicEditor绑定到textarea的快照。 以下问题不仅与下面的示例有关,而且可能与其他类似情况有关。 新手可以按照以下说明进行操作(如何澄清)吗? 如何使示例使用更少的步骤或更简单些? (是否可能具有与以下内容大致相同的内容?) 这使用
1回复

如何使类似HasHdbc的Snaplet在Snap上下文之外工作?

在使用HDBC Snaplet的教程中 ,它说:“设计HDBC Snaplet的目标之一是将函数与Handler单子或任何与Snap相关的单子分开,以便相同的查询也可以在外部运行Snap上下文,例如在命令行工具中。” 我正试图做到这一点。 类型类HasHdbc具有定义 可以通
2回复

在Snap中使用“ runghc”,而不抛出Webhandler异常。 使用tryIO仍然会出现错误

我正在尝试在snap内使用runGHC来仅过滤出可以编译的代码。 但是,我正在使用tryIO,但是当出现编译错误而不是仅返回空String时,我的Web处理程序仍然会引发异常。 但是,如果我传递未编译的“内容”,则处理程序将失败并显示 或任何编译器错误。 我以为tryIO应该
1回复

引用子Snaplet的首选方法

在Snap Framework中 ,Snaplet用于通过基于组件的界面将功能嵌入到其他Snaplet中:主Web应用程序是Snaplet,它通过经典的“ has-a”关系引用其他Snaplet,而子Snaplet可以依次引用其他Snaplets。 在查看各种Snaplet实现时,我看到了