And <A, B, C, D>(this InvertibleArrow <A, B> a1, InvertibleArrow <C, D> a2) { /* * Combines two arrows in parallel leading to an arrow on tuples, similar to the And * function on normal arrows */ InvertibleArrow <B, A> a1Inverted = a1.Invert(); InvertibleArrow <D, C> a2Inverted = a2.Invert(); return(new InvertibleArrow <Tuple <A, C>, Tuple <B, D> >( (Tuple <A, C> x) => { B leftResult = default(B); D rightResult = default(D); Parallel.Invoke( () => leftResult = a1.Invoke(x.Item1), () => rightResult = a2.Invoke(x.Item2)); return new Tuple <B, D>(leftResult, rightResult); }, (Tuple <B, D> x) => { A leftResult = default(A); C rightResult = default(C); Parallel.Invoke( () => leftResult = a1.Invert().Invoke(x.Item1), () => rightResult = a2.Invert().Invoke(x.Item2)); return new Tuple <A, C>(leftResult, rightResult); } )); }
public static void DemoInvertibleArrows() { Console.WriteLine("\t-- Invertible arrows demo --\n"); InvertibleArrow <int, int> arrow = Op.ArrowFunc((int x) => x * 2 + 5).Arr((int y) => (y - 5) / 2); InvertibleArrow <int, string> arrow2 = Op.ArrowFunc((int x) => x.ToString()).Arr((string y) => Convert.ToInt32(y)); InvertibleArrow <int, string> arrow3 = arrow.Combine(arrow2); string result = arrow3.Invoke(3); Console.WriteLine("3 into the arrow gives {0}", result); Console.WriteLine("{0} into the inverted arrow gives {1}", result, arrow3.Invert().Invoke(result)); }
Combine <A, B, C>(this InvertibleArrow <A, B> a1, InvertibleArrow <B, C> a2) { /* * Combine two invertible arrows end-to-end */ InvertibleArrow <B, A> a1Reversed = a1.Invert(); InvertibleArrow <C, B> a2Reversed = a2.Invert(); InvertibleArrow <A, C> result = new InvertibleArrow <A, C>( x => a2.Invoke(a1.Invoke(x)), x => a1Reversed.Invoke(a2Reversed.Invoke(x)) ); return(result); }
First <A, B, C>(this InvertibleArrow <A, B> arr) { /* * Similar to the First function for normal arrows, but obviously performing it on * InvertibleArrows instead. */ InvertibleArrow <B, A> reversed = arr.Invert(); return(new InvertibleArrow <Tuple <A, C>, Tuple <B, C> >( (Tuple <A, C> x) => new Tuple <B, C>( arr.Invoke(x.Item1), x.Item2 ), (Tuple <B, C> x) => new Tuple <A, C>( reversed.Invoke(x.Item1), x.Item2 ) )); }