Haskell 如何将代理值恢复到类型级别?
很难问这个问题,因为我不知道在这种情况下使用的确切术语。我将尝试通过我所面临的问题来表达我自己:Haskell 如何将代理值恢复到类型级别?,haskell,Haskell,很难问这个问题,因为我不知道在这种情况下使用的确切术语。我将尝试通过我所面临的问题来表达我自己: gogol库集通过使用 -gogol中的许多函数在此“权限列表”上是多态的,例如,谁的函数签名如下所示,其中s应该是这些代理的列表 newEnv :: (MonadIO m, MonadCatch m, AllowScopes s) => m (Env s) 现在,我们应该如何提供这个s类型级别参数: import Network.Google (allow, (!), newEnv, En
gogol
库集通过使用
-gogol
中的许多函数在此“权限列表”上是多态的,例如,谁的函数签名如下所示,其中s
应该是这些代理的列表
newEnv :: (MonadIO m, MonadCatch m, AllowScopes s) => m (Env s)
现在,我们应该如何提供这个s
类型级别参数:
import Network.Google (allow, (!), newEnv, Env)
import Network.Google.Sheets (driveScope, spreadsheetsScope)
type MyScopes = '[ "https://www.googleapis.com/auth/drive"
, "https://www.googleapis.com/auth/spreadsheets"
]
myEnv :: (MonadIO m, MonadCatch m) => Env MyScopes
mEnv = Network.Google.allow (driveScope ! spreadsheetScope) newEnv
-- or --
myEnv :: (MonadIO m, MonadCatch m) => Env MyScopes
mEnv = Network.Google.allow (Proxy :: Proxy MyScopes) newEnv
注意到上面代码片段中的重复吗?尽管果戈理的driveScope
库提供了driveScope
和spreadsheetsScope
,但我还是不得不再次将它们打印出来。是否有任何方法可以实现以下概念等效:
myEnv :: (MonadIO m, MonadCatch m) => Env (driveScope ! spreadsheetScope)
据我所知,这是不可能的-您不能以您想要的方式访问声明值的类型 正如@Daniel Wagner所评论的,这些库应该导出类型同义词——您可以向发出请求,但这种风格在所有不同的库中都使用,因此可能需要做一些工作 如果您不介意在本地复制类型,另一种选择是执行一些类型级编程以避免重复:
{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, TypeApplications #-}
...
import Network.Gogol.Auth.Scope (Nub, (++))
-- Type-level append, used by !
type family a !! b where
xs !! ys = Nub (xs ++ ys)
myEnv :: (MonadIO m, MonadCatch m) => Env (DriveScope !! SpreadsheetScope)
-- Here, @ just lets you pass in type parameters that don't appear in the body
mEnv = Network.Google.allow (Proxy @(DriveScope !! SpreadsheetScope)) newEnv
type DriveScope = '[...]
type SpreadsheetScope = '[...]
但这仍然意味着你要自己重复一遍。为什么不干脆省去类型签名呢?@melpomene不清楚这会有什么帮助。可能离这不远了。它们真的应该在整个库中公开类型同义词,而不是(或除了)代理。