RoutedT 在使用 Obelisk 路由时解释为 T.Text
RoutedT interpreted as T.Text when using Obelisk routes
我正在尝试使用 Obelisk 构建一个基本的 Web 应用程序,并且一直在学习本教程:https://github.com/obsidiansystems/obelisk/pull/733/files#diff-fe2dadb00af0583d3841e501760804eaR457
我不明白为什么当我的 Obelisk 安装是默认的 Obelisk 项目时我会收到这种类型错误,仅对上述教程进行修改以实现 "Profile" 和 "Event"/"Put In Work"页数。
我的最终目标是这些 routes/links 通过我在下面发布的 Frontend.hs 中定义的两个按钮连接(例如 elAttr "p" ("class" =: "button is-link is-large is-fullwidth") $ text "My Profile"
)。
这是我遇到的错误:
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)
| ^^^^^^^^^^^^^^^^^^^^
这是我的 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
)
这也是 Frontend.hs 的主要功能:
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 ()
}
这是我在编写 Reflex 应用程序时也会犯的一个常见错误。
解决方案是使用$
。为什么?让我们看看 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).
通过在 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 $
λ>
GHC 手册说“普通构造函数应用程序比中缀构造函数应用程序具有更高的优先级(因此 a : Foo a 解析为 : (Foo a))。”,因此在你的:
text "This event : " <> T.pack (show uidVal)
解释为
(text "This event : ") <> T.pack (show uidVal)
这显然是错误的。您可以通过显式限定表达式的范围来解决此问题:
text ("This event : " <> T.pack (show uidVal))
或者,只需使用前面提到的 $
运算符(这在反射代码库中通常是首选):
text $ "This event : " <> T.pack (show uidVal)
我正在尝试使用 Obelisk 构建一个基本的 Web 应用程序,并且一直在学习本教程:https://github.com/obsidiansystems/obelisk/pull/733/files#diff-fe2dadb00af0583d3841e501760804eaR457
我不明白为什么当我的 Obelisk 安装是默认的 Obelisk 项目时我会收到这种类型错误,仅对上述教程进行修改以实现 "Profile" 和 "Event"/"Put In Work"页数。
我的最终目标是这些 routes/links 通过我在下面发布的 Frontend.hs 中定义的两个按钮连接(例如 elAttr "p" ("class" =: "button is-link is-large is-fullwidth") $ text "My Profile"
)。
这是我遇到的错误:
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)
| ^^^^^^^^^^^^^^^^^^^^
这是我的 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
)
这也是 Frontend.hs 的主要功能:
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 ()
}
这是我在编写 Reflex 应用程序时也会犯的一个常见错误。
解决方案是使用$
。为什么?让我们看看 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).
通过在 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 $
λ>
GHC 手册说“普通构造函数应用程序比中缀构造函数应用程序具有更高的优先级(因此 a : Foo a 解析为 : (Foo a))。”,因此在你的:
text "This event : " <> T.pack (show uidVal)
解释为
(text "This event : ") <> T.pack (show uidVal)
这显然是错误的。您可以通过显式限定表达式的范围来解决此问题:
text ("This event : " <> T.pack (show uidVal))
或者,只需使用前面提到的 $
运算符(这在反射代码库中通常是首选):
text $ "This event : " <> T.pack (show uidVal)