/// <summary> /// Memoize the result /// </summary> public static Func <EitherPair <L, R> > Memo <L, R>(this Either <L, R> self) { var res = self(); return(() => res); }
/// <summary> /// Get the Left value /// NOTE: This throws an InvalidOperationException if the object is in the /// Right state /// </summary> public static bool IsLeft <L, R>(this Either <L, R> m) { return(m().IsLeft); }
/// <summary> /// Monadic append /// If the left-hand side or right-hand side are in a Left state, then Left propagates /// </summary> public static Either <L, R> Mappend <L, R>(this Either <L, R> lhs, Either <L, R> rhs) { if (rhs == null) { throw new ArgumentNullException("rhs"); } return(() => { var lhsV = lhs(); if (lhsV.IsLeft) { return lhsV; } else { var rhsV = rhs(); if (rhsV.IsLeft) { return rhsV; } else { if (lhsV.Right is IAppendable <R> ) { var lhsApp = lhsV.Right as IAppendable <R>; return new EitherPair <L, R>(lhsApp.Append(rhsV.Right)); } else { // TODO: Consider replacing this with a static Reflection.Emit which does this job efficiently. switch (typeof(R).ToString()) { case "System.Int64": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToInt64(lhsV.Right) + Convert.ToInt64(rhsV.Right)), typeof(R))); case "System.UInt64": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToUInt64(lhsV.Right) + Convert.ToUInt64(rhsV.Right)), typeof(R))); case "System.Int32": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToInt32(lhsV.Right) + Convert.ToInt32(rhsV.Right)), typeof(R))); case "System.UInt32": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToUInt32(lhsV.Right) + Convert.ToUInt32(rhsV.Right)), typeof(R))); case "System.Int16": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToInt16(lhsV.Right) + Convert.ToInt16(rhsV.Right)), typeof(R))); case "System.UInt16": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToUInt16(lhsV.Right) + Convert.ToUInt16(rhsV.Right)), typeof(R))); case "System.Decimal": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToDecimal(lhsV.Right) + Convert.ToDecimal(rhsV.Right)), typeof(R))); case "System.Double": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToDouble(lhsV.Right) + Convert.ToDouble(rhsV.Right)), typeof(R))); case "System.Single": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToSingle(lhsV.Right) + Convert.ToSingle(rhsV.Right)), typeof(R))); case "System.Char": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToChar(lhsV.Right) + Convert.ToChar(rhsV.Right)), typeof(R))); case "System.Byte": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToByte(lhsV.Right) + Convert.ToByte(rhsV.Right)), typeof(R))); case "System.String": return new EitherPair <L, R>((R)Convert.ChangeType((Convert.ToString(lhsV.Right) + Convert.ToString(rhsV.Right)), typeof(R))); default: throw new InvalidOperationException("Type " + typeof(R).Name + " is not appendable. Consider implementing the IAppendable interface."); } } } } }); }
/// <summary> /// Returns true if the monad object is in the Right state /// </summary> public static bool IsRight <L, R>(this Either <L, R> m) { return(m().IsRight); }