我使用的是 Servant 泛型,并為我的路由設定了資料型別:
data Routes route = Routes
{ getLiveness :: route :- GetLiveness,
getReadiness :: route :- GetReadiness,
getAuthVerifyEmailToken :: route :- GetAuthVerifyEmailToken,
postAuthEmail :: route :- PostAuthEmail,
...
}
deriving (Generic)
type BackendPrefix = "backend"
type AuthPrefix = "auth"
type GetLiveness = BackendPrefix :> "liveness" :> Get '[JSON] Text
type GetReadiness = BackendPrefix :> "readiness" :> Get '[JSON] Text
type GetAuthVerifyEmailToken = AuthPrefix :> "verify" :> "email" :> Capture "token" JWT :> RedirectResponse '[PlainText] NoContent
type PostAuthEmail = AuthPrefix :> "email" :> ReqBody '[JSON] AuthEmailRequest :> PostNoContent
前兩個使用相同的前綴"backend",所有其他的都有一個"auth"前綴。
但是,我現在想將"auth“前綴更改為“后端/身份驗證”。所以我嘗試更改:
type AuthPrefix = BackendPrefix :> "auth"
這導致錯誤
> ? Expected a type, but
> ‘"auth"’ has kind
> ‘ghc-prim-0.6.1:GHC.Types.Symbol’
> ? In the second argument of ‘(:>)’, namely ‘"auth"’
> In the type ‘BackendPrefix :> "auth"’
> In the type declaration for ‘AuthPrefix’
> |
> 34 | type AuthPrefix = BackendPrefix :> "auth"
> |
所以,我用Google搜索,發現你能做到這不使用通用的,你可以做的時候:
type APIv1 = "api" :> "v1" :> API
但我無法弄清楚如何使用泛型來做到這一點。
我想這留下了兩個問題:
- 上述錯誤是什么意思,我可以使用類似的東西
type AuthPrefix = BackendPrefix :> "auth"來創建更復雜的前綴嗎? - 在 Servant 中使用泛型時,有沒有辦法給一些路由加上一個前綴,而其他路由用不同的前綴?
uj5u.com熱心網友回復:
的定義:>是
data (path :: k) :> (a :: *)
請注意,正確的部分必須具有 kind *,也稱為Type. 這是一種“正常”的 Haskell 型別,例如Int或Bool具有提升值的型別。
但是,在型別級別運算式中BackendPrefix :> "auth",型別"auth"為Symbol,即型別級別字串的型別。種類不匹配,這會導致型別錯誤。
(你可能想知道,像"foo" :> "bar" :> Post '[JSON] User這樣的路徑怎么會起作用?原因是完全應用的Post有種類Type,完全應用的:>也有種類Type,并且:>在右邊關聯,例如"foo" :> ("bar" :> Post '[JSON] User),所以它全部檢查。)
解決方案?也許給出AuthPrefix一個型別引數,比如
type AuthPrefix restofpath = BackendPrefix :> "auth" :> restofpath
這樣我們就不會在一個Symbol.
我們現在必須AuthPrefix稍微不同地使用:
AuthPrefix ("email" :> ReqBody '[JSON] AuthEmailRequest :> PostNoContent)
這是因為新定義已經負責將 應用:>到路徑的其余部分。
uj5u.com熱心網友回復:
:>is infixr 4,這意味著它是右結合的。考慮這種型別:
type GetFoo = "backend" :> "auth" :> "foo" :> Get '[JSON] Text
它被解釋為好像你像這樣將它括起來:
type GetFoo = "backend" :> ("auth" :> ("foo" :> Get '[JSON] Text))
使用您嘗試的型別同義詞,它會像這樣被括號括起來:
type GetFoo = ("backend" :> "auth") :> ("foo" :> Get '[JSON] Text)
這顯然不是一回事,實際上甚至無效。
為了幫助理解,請考慮以下沒有高級型別的普通 Haskell 代碼:
xs = 1:2:3:4:5:6:[]
ys = 1:2:4:8:16:32:[]
現在想象你試圖寫這個:
zs = 1:2
xs = zs:3:4:5:6:[]
ys = zs:4:8:16:32:[]
它不起作用的原因與您不能擁有型別同義詞的原因完全相同。
最后一個例子:
x = 2 ^ 3 ^ 2 -- evaluates to 2 ^ (3 ^ 2) = 512
y = 2 ^ 3
x = y ^ 2 -- evaluates to (2 ^ 3) ^ 2 = 64
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/404597.html
標籤:
上一篇:Haskell,“是質數”函式
