Suppose I have a method that takes the Id
of a card issuer (think of loyalty cards for shops), and I want to get the status of the customer who made the most recent transaction. Yes this is a silly scenario, but it's easer than trying to describe the real one, and it's good enough to show the problem. The code shown here constitutes a working example, except for the last bit, which is where my question lies.
Here are two very simple types needed to support the workflow...
record CardIssuer(string Id, string Key);
enum CustomerStatus {
Active,
Inactive
}
I have some static methods that return an Either<string, T>
, where T
is specific to the actual method. The versions shown are stupidly simple for clarity...
static Either<string, CardIssuer> GetCardIssuer(string id) =>
id == "1" ? new CardIssuer("1", "abc") : new CardIssuer(id, "def");
static Either<string, int> GetLatestTransactionId(CardIssuer issuer) =>
issuer.Id == "1" ? 42 : 666;
static Either<string, CustomerStatus> GetCustomerStatus(int transactionId) =>
transactionId == 42 ? CustomerStatus.Active : CustomerStatus.Inactive;
I use these in a method like this...
static async Task<String> Process(string cardIssuerId) =>
await (
from issuer in GetCardIssuer(cardIssuerId).ToAsync()
from id in GetLatestTransactionId(issuer).ToAsync()
from status in GetCustomerStatus(id).ToAsync()
select status.ToString()
)
.Match(status => {
return status;
},
error => {
return $"Error: {error}";
});
All of the above works fine, and is all you need to reproduce the simple scenario.
Suppose I now have a requirement that the result is encrypted, using the issuer-specific encryption key held in the Key
property of CardIssuer
.
Modifying the Right
lambda is easy, I just change the last few lines of the query to look like this...
static async Task<String> Process(string cardIssuerId) =>
await (
from issuer in GetCardIssuer(cardIssuerId).ToAsync()
from id in GetLatestTransactionId(issuer).ToAsync()
from status in GetCustomerStatus(id).ToAsync()
// Next line changed, along with the first lambda to Match
select (issuer, status.ToString())
)
.Match((CardIssuer issuer, string status) => {
return Encrypt(status, issuer.Key);
},
error => {
// What do I do here?
});
This assumes an Encrypt
method...
static string Encrypt(string s, string key) =>
// Do some clever encryption with the key
"";
However, I don't know how to get the encryption key into the Left
lambda.
I know I can do this by modifying each of the Either
-returning methods to return a tuple containing the type they currently return, along with a string for the key, however, this means that a significant number of currently reusable (and reused) methods would now have to take in and pass out data that has nothing to do with them.
Is there a better way of passing data to the Left
lambda?