Skip to content

Instantly share code, notes, and snippets.

@matarillo
Forked from taichi/ExceptionalFunction.java
Last active August 29, 2015 14:12
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 matarillo/2fec645cedcdd2205430 to your computer and use it in GitHub Desktop.
Save matarillo/2fec645cedcdd2205430 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Linq;
class Program
{
static void Main(string[] args)
{
// 1. Trial.Ofの型引数を明示することで、実引数であるメソッド参照の型が決まる
var result1 = new[] { "aaa", "bbb", "ccc" }
.Select(Trial.Of<string, StreamReader>(File.OpenText))
.Select(x => x.Either(sr => 1, ex => 2))
.Select(x => x + 10);
// 2. 変数に代入することで、メソッド参照の型が決まる
Func<string, StreamReader> f_string_streamreader = File.OpenText;
var result2 = new[] { "aaa", "bbb", "ccc" }
.Select(Trial.Of(f_string_streamreader))
.Select(x => x.Either(sr => 1, ex => 2))
.Select(x => x + 10);
// 3. 変数に代入することで、メソッド参照の型が決まる (TextReader)
Func<string, TextReader> f_string_textreader = File.OpenText;
var result3 = new[] { "aaa", "bbb", "ccc" }
.Select(Trial.Of(f_string_textreader))
.Select(x => x.Either(tr => 1, ex => 2))
.Select(x => x + 10);
// おまけ1. Funcの変性 (戻り値は共変)
Func<string, StreamReader> f_subtype = null;
Func<string, TextReader> f_supertype = f_subtype;
// おまけ2. ITrialの変性 (共変)
ITrial<StreamReader> t_subtype = null;
ITrial<TextReader> t_supertype = t_subtype;
// おまけ3. FuncとITrialの変性 (戻り値は共変)
Func<string, Trial.Success<StreamReader>> ft_subtype = null;
Func<string, ITrial<TextReader>> ft_supertype = ft_subtype;
}
}
public interface ITrial<out T>
{
TResult Either<TResult>(Func<T, TResult> onSuccess, Func<Exception, TResult> onFailure);
}
public static class Trial
{
public static Func<T, ITrial<TResult>> Of<T, TResult>(Func<T, TResult> f)
{
return x =>
{
try
{
return new Success<TResult>(f(x));
}
catch (Exception e)
{
return new Failure<TResult>(e);
}
};
}
internal class Success<T> : ITrial<T>
{
private readonly T value;
internal Success(T value)
{
this.value = value;
}
public TResult Either<TResult>(Func<T, TResult> onSuccess, Func<Exception, TResult> onFailure)
{
return onSuccess(value);
}
}
internal class Failure<T> : ITrial<T>
{
private readonly Exception ex;
internal Failure(Exception ex)
{
this.ex = ex;
}
public TResult Either<TResult>(Func<T, TResult> onSuccess, Func<Exception, TResult> onFailure)
{
return onFailure(ex);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment