Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 学习堆栈和Monad变压器_Haskell_Monad Transformers_Happstack - Fatal编程技术网

Haskell 学习堆栈和Monad变压器

Haskell 学习堆栈和Monad变压器,haskell,monad-transformers,happstack,Haskell,Monad Transformers,Happstack,因此,我有一个项目,我认为它足够简单,可以学习,但足够复杂,非常有趣,我想使用Happstack库编写。在最基本的层面上,这个项目只是一个奇特的文件服务器,带有一些特定于域的REST方法(或者其他什么,我真的不在乎它是否是真正的RESTful),用于搜索和获取所述文件和元数据。因为我现在也在努力学习monad变形金刚,所以我决定这将是一个完美的学习项目。然而,我在启动时遇到了一些困难,特别是在如何构建我的transformer堆栈方面 现在,我只担心几件事:配置、错误报告、状态和日志,所以我从

因此,我有一个项目,我认为它足够简单,可以学习,但足够复杂,非常有趣,我想使用Happstack库编写。在最基本的层面上,这个项目只是一个奇特的文件服务器,带有一些特定于域的REST方法(或者其他什么,我真的不在乎它是否是真正的RESTful),用于搜索和获取所述文件和元数据。因为我现在也在努力学习monad变形金刚,所以我决定这将是一个完美的学习项目。然而,我在启动时遇到了一些困难,特别是在如何构建我的transformer堆栈方面

现在,我只担心几件事:配置、错误报告、状态和日志,所以我从

newtype MyApp a = MyApp {
    runMyApp :: ReaderT Config (ErrorT String (StateT AppState IO)) a
} deriving (...)
因为我总是在IO中,所以我可以很容易地使用hslogger来处理我的日志记录。但是我也知道我需要使用
ServerPartT
来与Happstack交互,因此

runMyApp :: ReaderT Config (ErrorT String (StateT AppState (ServerPartT IO))) a
我可以让它运行,查看请求等,但我遇到的问题是,需要为它实现
FilterMonad
,以便使用
dir
path
ok
,但我不知道如何为这种类型实现它。我只需要它将过滤器向下传递到底层monad。有人能给我一些关于如何实现这个显然至关重要的类型类的建议吗?或者,如果我只是做错了什么,那就把我引向正确的方向。我只看了几天Happstack,变形金刚对我来说还是很新的。我想我对它们的了解已经足够危险了,但我对它们的了解还不足以让我自己实现一个。非常感谢您提供的任何帮助


(X-posted from)

最简单的方法是从堆栈中删除error。如果您查看一下,您会发现Happstack为StateT和ReaderT定义了FilterMonad的内置passthrough实例,但没有为error定义任何实例。如果您真的想在堆栈中保留error,那么您需要为它编写一个passthrough实例。它可能看起来很像ReaderT的版本

instance (FilterMonad res m) => FilterMonad res (ReaderT r m) where
    setFilter f   = lift $ setFilter f
    composeFilter = lift . composeFilter
    getFilter     = mapReaderT getFilter
我倾向于认为您不应该将error烘焙到应用程序monad中,因为您不会总是处理可能失败的计算。如果您确实需要处理代码某个部分中的故障,您可以随时轻松地进入该部分,只需将
runerror
环绕该部分,然后根据需要使用
error
lift
return
。此外,transformer堆栈中的额外层会对每个绑定增加性能税。因此,虽然monad转换器的可组合性非常好,但是当性能是一个重要的考虑因素时,您通常希望节约使用它们

此外,我建议使用EitherT而不是ErrorT。这样你就可以充分利用这些神奇的东西。它有很多非常常见的方便功能,比如,等等

另外,如果你想看到一个真实的例子,你正在尝试做什么,看看Snap的。您的MyApp monad正是Snaplet设计用来解决的问题。处理程序有一些额外的复杂性,因为它是以一种通用的方式来解决问题的,这样Snap用户就不需要自己构建这个公共转换器堆栈。但如果你看一下,你会发现,在它的核心,它实际上只是读者和状态单子浓缩成一个整体