Last active
October 5, 2015 14:40
-
-
Save doubleday/41b9a28cd85581020546 to your computer and use it in GitHub Desktop.
Maybe types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static class Extensions | |
{ | |
public static T FirstOrValue<T>(this IEnumerable<T> sequence, T value) | |
{ | |
T result = value; | |
foreach(T item in sequence) | |
{ | |
result = item; | |
break; | |
} | |
return result; | |
} | |
} | |
static class IntParser | |
{ | |
public static Option<int> Parse(string value) | |
{ | |
int i; | |
return int.TryParse(value, out i) ? i : Option<int>.None; | |
} | |
} | |
class Bean | |
{ | |
public readonly int ID; | |
public readonly string Name; | |
public Bean (int id) | |
{ | |
ID = id; | |
Name = string.Format("Bean-{0}", ID); | |
} | |
} | |
abstract class BeanManager | |
{ | |
protected readonly List<Bean> Beans; | |
protected BeanManager() | |
{ | |
Beans = Enumerable.Range(0, 10).Select(i => new Bean(i)).ToList(); | |
} | |
} | |
class OptionBeanManager : BeanManager | |
{ | |
public Option<Bean> FindBean(int id) | |
{ | |
// auto lifting from linq | |
return Beans.FirstOrDefault(b => b.ID == id); | |
} | |
public IEnumerable<Bean> FindBeans(IEnumerable<int> ids) | |
{ | |
// monadic stuff | |
return ids.SelectMany(id => FindBean(id)); | |
} | |
public Option<string> FindName(int id) | |
{ | |
// propagation | |
return FindBean(id).Select(bean => bean.Name); | |
} | |
public IEnumerable<string> FindNames(IEnumerable<string> ids) | |
{ | |
// more monadic stuff: works with manager.FindNames(new [] { null, "a", "1", "12" }); | |
return ids | |
.SelectMany(id => IntParser.Parse(id)) | |
.SelectMany(id => FindName(id)); | |
} | |
public int LengthOfName(int id) | |
{ | |
return FindName(id).Match( | |
None: () => -1, | |
Some: name => name.Length | |
); | |
// integrates naturally with linq and custom linq extensions | |
// return FindName(id).Select(name => name.Length).FirstOrDefault(); | |
// return FindName(id).Select(name => name.Length).FirstOrValue(-1); | |
} | |
public void WithBean(int id, Action<Bean> callback) | |
{ | |
// YES! I want a side effect. Go sue me | |
FindBean(id).Match(Some: callback); | |
} | |
} | |
class MaybeBeanManager : BeanManager | |
{ | |
public Maybe<Bean> FindBean(int id) | |
{ | |
return Maybe.Return(Beans.FirstOrDefault(b => b.ID == id)); | |
} | |
public IEnumerable<Bean> FindBeans(IEnumerable<int> ids) | |
{ | |
// dont know how to get out of the maybe ... | |
//return ids | |
// .Select(FindBean) | |
// .Where(m => m.IsJust()); | |
} | |
public Maybe<string> FindName(int id) | |
{ | |
return FindBean(id).Bind(bean => Maybe.Return(bean.Name)); | |
} | |
public IEnumerable<string> FindNames(IEnumerable<string> ids) | |
{ | |
// dont know how to do this | |
return null; | |
} | |
public int LengthOfName(int id) | |
{ | |
// hm this works but I don't want to create / have a default value all the time | |
return FindName(id).ValueOr("").Length; | |
} | |
public void WithBean(int id, Action<Bean> callback) | |
{ | |
// hm can't access the value ... that's a bit too functional for me really | |
// how do i do this | |
var bean = FindBean(id); | |
if (bean.IsJust()) | |
{ | |
callback(bean.ValueOr((Bean)null)); | |
} | |
// I dont dare to do this :-) ... | |
// FindBean(id).Map(bean => { | |
// callback(bean); | |
// return Unit.Default; | |
// }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I just had a quick look, maybe have some time tonight.
We could have some useful additions to Seq(https://github.com/wooga/Wooga.Lambda-CSharp/blob/master/src/Wooga.Lambda/Data/Seq.cs)
Seq.choose
and having an id function that returns the object passed in:x=>x
.https://github.com/wooga/Wooga.Lambda-CSharp/blob/master/src/Wooga.Lambda/Data/Seq.cs#L18
https://msdn.microsoft.com/en-us/library/ee340250.aspx
...