Skip to content

Instantly share code, notes, and snippets.

@gowland
Last active December 15, 2015 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gowland/5313861 to your computer and use it in GitHub Desktop.
Save gowland/5313861 to your computer and use it in GitHub Desktop.
Invalidatable monad inspired by Eric Lippert's series on monads. I intended to use this class to wrap data that is expensive to generate but that may not be valid for the duration of the application's life time.I ended not using it, so it is unproven and untested and provided mostly for my own reference.
public class Invalidatable<T>
{
public T Value { get; private set; }
public Func<bool> IsInvalidated { get; private set; }
public Invalidatable(T value, Func<bool> isInvalidated)
{
Value = value;
this.IsInvalidated = isInvalidated;
}
public Invalidatable(T value) : this(value, () => false) { }
public static Invalidatable<R> Bind<A, R>(
Invalidatable<A> invalidatable, Func<A, Invalidatable<R>> function)
{
Invalidatable<R> result = function(invalidatable.Value);
return new Invalidatable<R>(result.Value, () => invalidatable.IsInvalidated() || result.IsInvalidated());
}
}
/// Example usage
class MyDataSource
{
private bool IsStillValid(ExpensiveComputedData computed)
{
// Insert logic here to determine whether or not the class is still valid
return true;
}
public Invalidatable<ExpensiveComputedData> GetExpensiveComputedData()
{
//Calculate data
ExpensiveComputedData computed = new ExpensiveComputedData();
return new Invalidatable<ExpensiveComputedData>(computed, () => !this.IsStillValid(computed));
}
}
class MyDataClient
{
public MyDataSource Data {get; private set};
private Invalidatable<ExpensiveComputedData> Computed;
private trustedTime = 24;
public MyDataClient(MyDataSource data)
{
Data = data;
// Get the computed data
Computed = data.GetExpensiveComputedData();
}
// Derive data from the invalidatable data that is time dependent
private static Invalidatable<int> DerivitiveCalculation(Invalidatable<ExpensiveComputedData> computedValue)
{
// Timeout in 24 hours
DateTime timeoutDate = DateTime.UtcNow.Add(trustedTime);
return new Invalidatable<int>(computedValue.IntegerValue, () => DateTime.UtcNow < timeoutDate);
}
// Get some value from the expensive computed value
public Invalidatable<int> GetDataFromExpensiveComputed()
{
if (computed.IsInvalidated())
{
computed = data.GetExpensiveComputedData();
}
// This will return an Invalidatable<int> that can be invalidated either by the time out or by the original data source no longer considering the computed data valid
return computed.Bind(DerivitiveCalculation);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment