【问题标题】:Confusion About Yesod Widget Related Types关于 Yesod 小部件相关类型的混淆
【发布时间】:2016-01-05 10:39:15
【问题描述】:

我刚开始玩 Yesod,虽然我已经可以得到一些有趣的结果,但我很难清楚地理解它的一些类型(可能是因为我不熟悉 Template Haskell)。

usual way 将 hamlet sn-p 传递给 defaultLayout 函数是通过 toWidget 函数。所以按照下面对ham1和ham2的定义,defaultLayout中正确的指令分别是toWidget ham1ham2

我的问题:在下面的(工作)代码中,为什么指令toWidget ham2 编译,而它是与ham1 完全不同的动物?我想这意味着 ham1 的类型 (ham1 :: t -> Text.Blaze.Internal.Markup (*)) 和 ham2 的类型 (ham2 :: Widget) 都是 ToWidget 类的实例,但在阅读此 @987654322 时这对我来说并不完全明显@。

(*)另外,如果有人能告诉我ham1是否有比t -> Text.Blaze.Internal.Markup“更好”的类型同义词,那就太好了。

代码:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

module Main where

import Yesod
import Text.Blaze.Internal (Markup)

data App = App
instance Yesod App

mkYesod "App" [parseRoutes|
/ HomeR GET
|]

getHomeR :: Handler Html
getHomeR = defaultLayout $ do
    setTitle "Some Title"

    toWidget ham1   -- usual way to produce a Widget from hamlet snippet
    toWidget ham2   -- ??
    ham2            -- already of type Widget


ham1 :: t -> Text.Blaze.Internal.Markup -- explicit signature for reference only
ham1 = [hamlet|
<h1> 1) Hello
<h2> World!
 |]

ham2 :: Widget
ham2 = 
    toWidget [hamlet|
<h1> 2) Hello
<h2> World!
 |]

main :: IO ()
main = do
    warp 3000 App

输出:

【问题讨论】:

    标签: haskell yesod hamlet


    【解决方案1】:

    我不完全确定要问什么,所以我将解释它是如何工作的, 我希望它会是相关的。

    defaultLayout 需要一个小部件来很好地放置它……默认布局。因此你的 do-block 单元组合小部件。要通过类型检查器,每行 do-block 应该是 Widget a 类型(或 WidgetT App IO a,是你的 站点的数据类型是App)。 ToWidget 的实例是可以 转换为小部件。 Widgets 也是此类的实例 作为render -&gt; Html 的东西。鉴于Html 是类型同义词 Text.Blaze.Internal.Markup,你的ham1 是一个完美的候选人 传递给toWidget,见源代码:

    instance render ~ RY site => ToWidget site (render -> Html) where
        toWidget x = …
    

    (~) 放置额外的约束,它告诉类型检查器(在这个实例之后 已经被它选择了)顺便说一下render必须有类型RY sitesite 一种幻象类型,它确保系统的不同部分 属于同一个站点,如果您使用脚手架,通常是AppRY site 使用另一个类型同义词 RY 传递它 site 变量,结果 像这样输入:

    Route App -> [(Text, Text)] -> Text
    

    这是ham1 采用的参数类型。

    所以这些实例允许您将不同的东西转换成小部件, 包括hamlet quasi-quoter 产生的功能,没有魔法 在这里。

    【讨论】:

    • 谢谢马克。抱歉,如果我的问题不是很清楚,但在代码的三个连续指令中:toWidget ham1toWidget ham2ham2toWidget ham2 是我不明白的类型,因为 ham2 已经定义为toWidget something 类型,所以 toWidget ham2 似乎将 toWidget 两次“复合”成 toWidget (toWidget something)。 (我会设法澄清我的问题并进行编辑)
    • @JeanAnthelme, WidgetToWidget 的实例(从某些角度来看可能会让人感到困惑),所以你可以在toWidget widget 中执行widget 已经是Widget
    • 谢谢。是的,我同意,我的问题相当于“Widget 是 ToWidget 的实例”,我无法从 ToWidget 的实例定义中立即理解,但您让我走上了正确的轨道,我会再过一遍。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 2012-12-17
    • 2015-06-19
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 2017-07-20
    相关资源
    最近更新 更多