Skip to content

Instantly share code, notes, and snippets.

@doubleday
Last active October 5, 2015 14:40
Show Gist options
  • Save doubleday/41b9a28cd85581020546 to your computer and use it in GitHub Desktop.
Save doubleday/41b9a28cd85581020546 to your computer and use it in GitHub Desktop.
Maybe types
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;
// });
}
}
@devboy
Copy link

devboy commented Oct 5, 2015

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)

dont know how to get out of the maybe ...

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
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment