简体   繁体   English

RoutedT 在使用 Obelisk 路线时被解释为 T.Text

[英]RoutedT interpreted as T.Text when using Obelisk routes

I am trying to build a basic web app with Obelisk and have been following this tutorial: https://github.com/obsidiansystems/obelisk/pull/733/files#diff-fe2dadb00af0583d3841e501760804eaR457我正在尝试使用 Obelisk 构建一个基本的 web 应用程序,并且一直在关注本教程: https://github.com/obsidiansystems/obelisk/pull/733/files#diff-fe2dadb00af05803d48eaR45758

I do not understand why I would get this type error when my Obelisk installation is a default Obelisk project with only the modifications from the tutorial above to implement "Profile" and "Event"/"Put In Work" pages.我不明白为什么当我的 Obelisk 安装是一个默认的 Obelisk 项目时我会收到这种类型的错误,并且只对上面的教程进行了修改以实现“Profile”和“Event”/“Put In Work”页面。

My ultimate goal is that these routes/links are connected via the two buttons defined in my Frontend.hs that I have posted below (eg elAttr "p" ("class" =: "button is-link is-large is-fullwidth") $ text "My Profile" ).我的最终目标是这些路由/链接通过我在下面发布的 Frontend.hs 中定义的两个按钮连接(例如elAttr "p" ("class" =: "button is-link is-large is-fullwidth") $ text "My Profile" )。

This is the error I'm getting:这是我得到的错误:

frontend/src/Frontend.hs:41:41-60: error:
    • Couldn't match type ‘T.Text’ with ‘RoutedT t EventId m ()’
      Expected type: RoutedT t a m ()
        Actual type: T.Text
    • In the second argument of ‘(<>)’, namely ‘T.pack (show uidVal)’
      In the expression: text "This event : " <> T.pack (show uidVal)
      In the second argument of ‘($)’, namely
        ‘\ (EventId uidVal)
           -> text "This event : " <> T.pack (show uidVal)’
    • Relevant bindings include
        dUserId :: Dynamic t EventId
          (bound at frontend/src/Frontend.hs:39:13)
   |
41 |                 text "This event : " <> T.pack (show uidVal)
   |                                         ^^^^^^^^^^^^^^^^^^^^
frontend/src/Frontend.hs:48:40-59: error:
    • Couldn't match type ‘T.Text’ with ‘RoutedT t UserId m ()’
      Expected type: RoutedT t a m ()
        Actual type: T.Text
    • In the second argument of ‘(<>)’, namely ‘T.pack (show uidVal)’
      In the expression: text "This user : " <> T.pack (show uidVal)
      In the second argument of ‘($)’, namely
        ‘\ (UserId uidVal) -> text "This user : " <> T.pack (show uidVal)’
    • Relevant bindings include
        dUserId :: Dynamic t UserId
          (bound at frontend/src/Frontend.hs:46:13)
   |
48 |                 text "This user : " <> T.pack (show uidVal)
   |                                        ^^^^^^^^^^^^^^^^^^^^

This is an excerpt from my Common.Route file, which is the only half-implemented part of the tutorial... so maybe this is the problem?这是我的 Common.Route 文件的摘录,这是本教程中唯一实现一半的部分......所以也许这就是问题所在?

data FrontendRoute :: * -> * where
  FrontendRoute_Main :: FrontendRoute ()
  -- This type is used to define frontend routes, i.e. ones for which the backend will serve the frontend.
  FrontendRoute_MyProfile :: FrontendRoute UserId
  FrontendRoute_PutInWork :: FrontendRoute EventId

fullRouteEncoder
  :: Encoder (Either Text) Identity (R (FullRoute BackendRoute FrontendRoute)) PageName
fullRouteEncoder = mkFullRouteEncoder
  (FullRoute_Backend BackendRoute_Missing :/ ())
  (\case
      BackendRoute_Missing -> PathSegment "missing" $ unitEncoder mempty)
  (\case
      FrontendRoute_Main -> PathEnd $ unitEncoder mempty
      -- FrontendRoute_MyProfile -> PathSegment "user" _todo
      -- FrontendRoute_PutInWork -> PathSegment "event" _todo
      )

Here is the primary function from Frontend.hs as well:这里也是来自 Frontend.hs 的主要 function:

frontend :: Frontend (R FrontendRoute)
frontend = Frontend
  { _frontend_head = do
      el "title" $ text "The App Name"
      elAttr "link" ("href" =: static @"bulma.css" <> "type" =: "text/css" <> "rel" =: "stylesheet") blank
  , _frontend_body = subRoute_ $ \case          -- https://github.com/obsidiansystems/obelisk/pull/733/files#diff-fe2dadb00af0583d3841e501760804eaR425
        FrontendRoute_PutInWork -> do
            text "We're on the Put In Work page! But which event?"
            dUserId <- askRoute
            dyn_ $ ffor dUserId $ \(EventId uidVal) ->
                text "This event : " <> T.pack (show uidVal)
            routeLink (FrontendRoute_Main :/ ()) $
                text "To the main page!"
        FrontendRoute_MyProfile -> do
            text "We're on the My Profile page! But which user?"
            dUserId <- askRoute
            dyn_ $ ffor dUserId $ \(UserId uidVal) ->
                text "This user : " <> T.pack (show uidVal)
            routeLink (FrontendRoute_Main :/ ()) $
                text "To the main page!"
        FrontendRoute_Main -> do
            elClass "div" "content" $ do
            elAttr "h1" ("class" =: "content") $ text "Welcome to the app!"
            el "h2" $ text $ T.pack commonStuff
            elAttr "p" ("class" =: "button is-primary is-large is-fullwidth") $ text "Put In Work"
            elAttr "p" ("class" =: "button is-link is-large is-fullwidth") $ text "My Profile"

            elAttr "p" ("class" =: "box") $ text "News about the app and the world (box is color-coded based on content type), special offers from partners, prompts that there is a new partner nearby, and prompts to push yourself harder eventually.  At launch, it's just a welcome text / helper note."

            routeLink (FrontendRoute_MyProfile :/ User 42) $
                text "Visit the page of User # 42"
    return ()

}

This is a common mistake I also make when writing Reflex apps.这也是我在编写 Reflex 应用程序时常犯的一个错误。

The solution is to use $ .解决方案是使用$ Why?为什么? Let's look at the fixity declarations ,让我们看看固定性声明

There are three kinds of fixity, non-, left- and right-associativity (infix, infixl, and infixr, respectively), and ten precedence levels, 0 to 9 inclusive (level 0 binds least tightly, and level 9 binds most tightly).有 3 种固定性,非结合性、左结合性和右结合性(分别为中缀、中缀和中缀)和十个优先级,包括 0 到 9(0 级绑定最紧密,9 级绑定最紧密) .

by playing in GHCi repl,通过玩 GHCi repl,

λ> :i (<>)
class Semigroup a where
  (<>) :: a -> a -> a
  ...
        -- Defined in ‘GHC.Base’
infixr 6 <>
λ> :i ($)
($) :: (a -> b) -> a -> b       -- Defined in ‘GHC.Base’
infixr 0 $
λ>

The GHC manual says " normal constructor application has higher precedence than infix constructor application (thus a: Foo a parses as a: (Foo a)). ", therefore in your: GHC 手册说“普通构造函数应用程序比中缀构造函数应用程序具有更高的优先级(因此 a: Foo a 解析为 a: (Foo a))。 ”,因此在你的:

text "This event : " <> T.pack (show uidVal)

it is interpreted as它被解释为

(text "This event : ") <> T.pack (show uidVal)

which is obviously wrong.这显然是错误的。 You can fix this by explicitly scoping the expression:您可以通过明确限定表达式的范围来解决此问题:

text ("This event : " <> T.pack (show uidVal))

Or, simply by using the aforementioned $ operator (which is generally preferred in reflex code base):或者,只需使用前面提到的$运算符(这在反射代码库中通常是首选):

text $ "This event : " <> T.pack (show uidVal)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM