Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何将代理值恢复到类型级别?_Haskell - Fatal编程技术网

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不清楚这会有什么帮助。可能离这不远了。它们真的应该在整个库中公开类型同义词,而不是(或除了)代理。