【发布时间】:2020-04-10 23:47:51
【问题描述】:
用良好的形式编码 haskell 的问题,而不是“它有效”。
当用户在该页面上时,我们希望我们的菜单导航项具有突出显示的 CSS 类。
简单。
这是我的路线:
...
/simple SimpleR GET POST
/search SearchFormR GET POST
/searchresults/#Int/#Text SearchResultsR GET
...
在我的小村庄模板中,我有以下内容。这非常有效,当用户在该页面上时,链接会突出显示。路线很简单。
<li .nav-item>
<a .nav-link :Just SimpleR == mcurrentRoute:.active href=@{SimpleR}>
Simple page
当用户使用SearchFormR 或SearchResultsR 时,应突出显示此链接。
<li .nav-item>
<a .nav-link :((Just (SearchResultsR _ _)) == mcurrentRoute) || (Just SearchFormR == mcurrentRoute):.active href=@{SearchFormR}>
Search
这段代码不起作用,因为SearchResultsR 路由构造函数需要传递给它的两个东西。我不能像上面那样写_ _,因为构造函数需要一个文字值。此外,构造函数的结果无论如何都会与== 与实际路由进行比较,除非两个参数恰好相同,否则它不会匹配。
如果没有_ _,我当然会遇到类型错误,预计还会有两件事传递给SearchResultsR 构造函数。
也就是说,我想检查我们是否在任何SearchResultsR 路由上,而不仅仅是匹配SearchResultsR 123 "abc"。
我的第一个想法是制作一个函数将路由转换为字符串,然后检查该字符串是否包含路由的字符串,但这很糟糕,而不是 haskell / typesafe 方式。
我的第二次尝试是使用模式匹配:
Foundation.hs:
isThisRouteSearchResultsR :: Maybe (Route App) -> Bool
isThisRouteSearchResultsR (Just (SearchResultsR _ _)) = True
isThisRouteSearchResultsR _ = False
哈姆雷特模板:
<li .nav-item>
<a .nav-link :(isThisRouteSearchResultsR mcurrentRoute) || (Just SearchR == mcurrentRoute) :.active href=@{SearchR}>
Search
但这似乎也好不到哪里去。如果我有更多包含动态部分的路线怎么办? 这样做的正确方法是什么?我查看了haskellers网站源代码,但找不到答案
【问题讨论】:
-
我喜欢你的第二种方法。事实上,我什至会将其重构为单个函数,这样您就不会在 hamlet 文件中执行
|| (Just SearchR == mcurrentRoute)。目标是通常将所有逻辑保留在 Haskell 文件中,并在 Hamlet 文件中保持最小化。如果您有更多动态部分,我将只创建一个函数来处理它们(即组合许多单个函数来做我想做的事)。 -
感谢 Sibi 的赞誉!关于“目标通常是”的提示非常有价值。我想以 Yesod 的方式做事。有趣的是,我想我不完全理解,单个函数的返回类型是什么?我想返回一个像“SearchResultsR”这样的字符串来比较,但这看起来很乱。
-
返回类型将为
Bool。 -
谢谢。一个例子:
:(isThisRouteSearchResultsROrSearchR mcurrentRoute) :.active或者可以做:(isThisRouteSearchResultsR mcurrentRoute) || (isThisRouteSearchR mcurrentRoute) :.active也许这些函数可以通过一些模板 Haskell 在 Foundation.hs 中自动生成。 -
没错。我更喜欢第一个解决方案
:(isThisRouteSearchResultsROrSearchR mcurrentRoute) :.active,但这只是我。我不会为此使用 Template Haskell,因为它非常简单(且可读)!