Open MichaelXavier opened 7 years ago
A bit of an update after bashing on this for a while: from what I can tell, scopes are treated like a set, but they are order dependent. What I did was write a mkEnv
function in my Google Cloud module that will make an env with the set of all scopes used by all the API calls the module supports. To test it, I then wrote a function that used this env and called every one of those functions. Initially it would not typecheck and presented me with 2 equivalent sets of scopes, one required and one given. I reordered the construction of the scope set to align with the set it demanded and it typechecked.
So going forward:
I ran into this problem as well. For example, when downloading and uploading a bytestring in the same function, the constraints become :
HasScope'
s1
'["https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/devstorage.full_control",
"https://www.googleapis.com/auth/devstorage.read_write"]
~ 'True,
HasScope'
s1
'["https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/cloud-platform.read-only",
"https://www.googleapis.com/auth/devstorage.full_control",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/devstorage.read_write"]
~ 'True) =>
I believe getting rid of type-level lists and declaring distinct constraints for each API scope (HasScope s CloudPlatform, HasScope s DevStorageRW
etc.) would make this interface more ergonomical.
I've got a module in my project that's the single interface to all of my usage of google cloud services. Currently, each individual function is rebuilding the
env
each time, which seems pretty wasteful. I would rather the user be able to pass in an env to each function.The problem comes with the scopes needed for each function:
The problem with 1 is if one of my google functions uses multiple google functions internally, the required type signature does not seem to concatenate lists but forces me to specify them individually, duplicates and all. So if I use
foo
which requires'[a, b, c]
andbar
which requires'[b, c, d]
, thenfooBar
's constraints won't require(HasScope s '[a, b, c, d] ~ True) => Env s -> ...
but rather(HasScope s '[a, b, c] ~ True, HasScope s '[b, c, d]) => Env s -> ...
, which can get really repetitive the more you use. I am not willing to forgo writing type signatures for toplevel functions.The problem with 2 is
envScopes :: Lens' a (Proxy s)
uses aLens'
which does not allow type-changing, so I cannot do something likelet env' = env & envScopes .~ neededScopes
because that changess
and that lens will not allow it.I tried to look at the examples for guidance but because they set up the env and set scopes in one shot, they can't really model the scenario of the user passing in an env to something that demands a certain set of scopes. What should I do?