1 /** This module implements a variety of classes derived from Function. */
2 module generald.functions;
3 
4 import std.typecons, std.traits;
5 
6 alias Maybe = Nullable;
7 
8 /// A class representing a function.
9 abstract class Function(A, B)
10 {
11 	abstract B opCall(A);
12 	alias InputType = A;
13 	alias OutputType = B;
14 }
15 
16 /// Template for converting a function to Function instance.
17 class RealFunction(alias f, A=ParameterTypeTuple!f[0], B=ReturnType!f) : Function!(A, B)
18 {
19 	pragma(msg, "RealFunction(", A.stringof, " -> ", ParameterTypeTuple!f[0].stringof, " -> ", ReturnType!f.stringof, " -> ", B.stringof, ")");
20 	override B opCall(A x)
21 	{
22 		return f(x);
23 	}
24 	mixin Singleton;
25 }
26 
27 ///
28 unittest
29 {
30 	static int f(long x)
31 	{
32 		return cast(int)((x >> 32) ^ (x & ((1UL << 32) - 1)));
33 	}
34 	static assert (is (RealFunction!f : Function!(long, int)));
35 	static assert (is (RealFunction!(f, int, int) : Function!(int, int)));
36 	static assert (is (RealFunction!(f, int, long) : Function!(int, long)));
37 	static assert (is (RealFunction!(f, long, long) : Function!(long, long)));
38 }
39 
40 /// Identity function.
41 T id(T)(T x)
42 {
43 	return x;
44 }
45 
46 /// ditto
47 alias IdentityFunction(T) = RealFunction!(id!T);
48 
49 ///
50 unittest
51 {
52 	auto f = IdentityFunction!int.get;
53 	assert (f(0) == 0);
54 }
55 
56 /// Compose two Functions.
57 class ComposedFunction(A, B, C, D) : Function!(A, D)
58 	if (is (B : C))
59 {
60 	Function!(A, B) f;
61 	Function!(C, D) g;
62 	this (Function!(A, B) f, Function!(C, D) g)
63 	{
64 		this.f = f;
65 		this.g = g;
66 	}
67 	override D opCall(A x)
68 	{
69 		return g(f(x));
70 	}
71 }
72 
73 /// ditto
74 auto compose(F, G)(F f, G g)
75 	if (is (F : Function!(F.InputType, F.OutputType)) &&
76 		is (G : Function!(G.InputType, G.OutputType)) &&
77 		is (F.OutputType : G.InputType))
78 {
79 	return new ComposedFunction!(F.InputType, F.OutputType, G.InputType, G.OutputType)(f, g);
80 }
81 
82 ///
83 unittest
84 {
85 	auto f = RealFunction!(triple!int).get.compose(RealFunction!(increment!int).get);
86 	auto g = RealFunction!(increment!int).get.compose(RealFunction!(triple!int).get);
87 	assert (f(0) == 1);
88 	assert (f(1) == 4);
89 	assert (g(0) == 3);
90 	assert (g(1) == 6);
91 }
92 
93 /// Curry a function.
94 class CurriedFunction(A, B, C) : Function!(A, Function!(B, C))
95 {
96 	Function!(Tuple!(A, B), C) uncurried;
97 	this (Function!(Tuple!(A, B), C) uncurried)
98 	{
99 		this.uncurried = uncurried;
100 	}
101 	class Partial : Function!(B, C)
102 	{
103 		A x;
104 		this (A x)
105 		{
106 			this.x = x;
107 		}
108 		override C opCall(B x)
109 		{
110 			return uncurried(this.x.tuple(x));
111 		}
112 	}
113 	override Function!(B, C) opCall(A x)
114 	{
115 		return new Partial(x);
116 	}
117 }
118 
119 /// ditto
120 auto curry(F)(F f)
121 {
122 	static if (is (F.InputType : Tuple!(A, B), A, B))
123 		return new CurriedFunction!(A, B, F.OutputType)(f);
124 	else static assert (false);
125 }
126 
127 ///
128 unittest
129 {
130 	static class F : Function!(Tuple!(int, int), int)
131 	{
132 		override int opCall(Tuple!(int, int) x)
133 		{
134 			return x[0] + x[1];
135 		}
136 		mixin Singleton;
137 	}
138 	auto cf = F.get.curry;
139 	static assert (is (typeof (cf) : Function!(int, Function!(int, int))));
140 }
141 
142 /// Uncurry a function.
143 class UncurriedFunction(A, B, C) : Function!(Tuple!(A, B), C)
144 {
145 	Function!(A, Function!(B, C)) curried;
146 	this (Function!(A, Function!(B, C)) curried)
147 	{
148 		this.curried = curried;
149 	}
150 	override C opCall(Tuple!(A, B) x)
151 	{
152 		return curried(x[0])(x[1]);
153 	}
154 }
155 
156 /// ditto
157 auto uncurry(F)(F f)
158 {
159 	static if (is (F.OutputType == Function!(B, C), B, C))
160 		return new UncurriedFunction!(F.InputType, B, C)(f);
161 	else static assert (false);
162 }
163 
164 ///
165 unittest
166 {
167 	static class G : Function!(int, Function!(int, int))
168 	{
169 
170 		class g : Function!(int, int)
171 		{
172 			int x;
173 			this (int x)
174 			{
175 				this.x = x;
176 			}
177 			override int opCall(int x)
178 			{
179 				return this.x + x;
180 			}
181 		}
182 		override Function!(int, int) opCall(int x)
183 		{
184 			return new g(x);
185 		}
186 		mixin Singleton;
187 	}
188 	auto ug = G.get.uncurry;
189 	static assert (is (typeof (ug) : Function!(Tuple!(int, int), int)));
190 }
191 
192 /// Function which always return Null.
193 Maybe!A nothing(A)()
194 {
195 	return Maybe!A();
196 }
197 
198 /// Return function for Maybe.
199 Maybe!A just(A)(A x)
200 {
201 	return Maybe!A(x);
202 }
203 /// ditto
204 alias maybeReturn(A) = just!A;
205 /// ditto
206 alias MaybeReturn(A) = RealFunction!(maybeReturn!A);
207 
208 /// Bind function for Maybe: (a -> Maybe b) -> (Maybe a -> Maybe b).
209 class MaybeBind(A, B) : Function!(Maybe!A, Maybe!B)
210 {
211 	Function!(A, Maybe!B) f;
212 	this (Function!(A, Maybe!B) f)
213 	{
214 		this.f = f;
215 	}
216 	override Maybe!B opCall(Maybe!A x)
217 	{
218 		if (x.isNull)
219 			return nothing!B;
220 		return f(x.get);
221 	}
222 }
223 
224 /// ditto
225 auto maybeBind(F)(F f)
226 {
227 	static if (is (F.OutputType : Maybe!B, B))
228 		return new MaybeBind!(F.InputType, B)(f);
229 	else static assert (false);
230 }
231 
232 /// Map function for Maybe.
233 auto maybeMap(F)(F f)
234 	if (is (F : Function!(A, B), A, B))
235 {
236 	return f.compose(MaybeReturn!(F.OutputType).get).maybeBind;
237 }
238 
239 ///
240 unittest
241 {
242 	auto maybeId = maybeMap(RealFunction!(id!int).get);
243 	assert (maybeId(just(0)) == just(0));
244 }
245 
246 /// Compose two Functions f and g where f emits a Maybe!B and g takes a B.
247 auto maybeCompose(F, G)(F f, G g)
248 {
249 	return f.compose(g.maybeBind);
250 }
251 
252 ///
253 unittest
254 {
255 	auto c = RealFunction!(collatz!int).get;
256 	auto lc = c.maybeCompose(c).maybeCompose(c);
257 	auto rc = c.maybeCompose(c.maybeCompose(c));
258 	foreach (i; 0..10)
259 		assert (lc(i).maybeEqual(rc(i)));
260 }
261 
262 /// Function from Maybe to void can be constructed from a Function to void.
263 class MaybeSink(A) : Function!(Maybe!A, void)
264 {
265 	Function!(A, void) sink;
266 	this (Function!(A, void) sink)
267 	{
268 		this.sink = sink;
269 	}
270 	override void opCall(Maybe!A x)
271 	{
272 		if (x.isNull)
273 			return;
274 		sink(x);
275 	}
276 }
277 
278 /// ditto
279 auto maybeSink(S)(S sink)
280 	if (is (S : Function!(A, void), A))
281 {
282 	return new MaybeSink!(S.InputType)(sink);
283 }
284 
285 /// Maybe do something, and return null.
286 class MaybeNothing(A, B, C=void) : Function!(A, Maybe!B)
287 {
288 	Function!(A, C) sink;
289 	this (Function!(A, C) sink)
290 	{
291 		this.sink = sink;
292 	}
293 	override Maybe!B opCall(A x)
294 	{
295 		sink(x);
296 		return nothing!B;
297 	}
298 }
299 
300 /// ditto
301 auto maybeNothing(B, F)(F f)
302 {
303 	return new MaybeNothing!(F.InputType, B, F.OutputType)(f);
304 }
305 
306 
307 /// Either type.
308 struct Either(A, B)
309 	if (!is (A : B) && !is (B : A))
310 {
311 	this (A a)
312 	{
313 		this.nonNull = true;
314 		this.which = false;
315 		this._a = a;
316 	}
317 	this (B b)
318 	{
319 		this.nonNull = true;
320 		this.which = true;
321 		this._b = b;
322 	}
323 	typeof (this) opAssign(A a)
324 	{
325 		this.nonNull = true;
326 		this.which = false;
327 		this._a = a;
328 		return this;
329 	}
330 	typeof (this) opAssign(B b)
331 	{
332 		this.nonNull = true;
333 		this.which = true;
334 		this._b = b;
335 		return this;
336 	}
337 	string toString()
338 	{
339 		import std.conv;
340 		if (!which)
341 			return _a.to!string;
342 		else
343 			return _b.to!string;
344 	}
345 	alias Left = A;
346 	alias Right = B;
347 private:
348 	bool nonNull, which;
349 	A _a;
350 	B _b;
351 	@property A a()
352 	in
353 	{
354 		assert (this.nonNull);
355 		assert (!this.which);
356 	}
357 	body
358 	{
359 		return _a;
360 	}
361 	@property B b()
362 	in
363 	{
364 		assert (this.nonNull);
365 		assert ( this.which);
366 	}
367 	body
368 	{
369 		return _b;
370 	}
371 }
372 
373 alias Left(A) = Typedef!(A, A.init, "left");
374 alias Right(A) = Typedef!(A, A.init, "right");
375 alias Either(A) = Either!(Left!A, Right!A);
376 
377 /// Tuple of functions, which takes an Either.
378 class EitherFunction(A, B, C) : Function!(Either!(A, B), C)
379 {
380 	Function!(A, C) f;
381 	Function!(B, C) g;
382 	this (Function!(A, C) f, Function!(B, C) g)
383 	{
384 		this.f = f;
385 		this.g = g;
386 	}
387 	override C opCall(Either!(A, B) x)
388 	{
389 		if (!x.which)
390 			return f(x.a);
391 		else
392 			return g(x.b);
393 	}
394 }
395 
396 /// ditto
397 auto eitherFunction(F, G)(F f, G g)
398 	if (is (F.OutputType == G.OutputType))
399 {
400 	return new EitherFunction!(F.InputType, G.InputType, F.OutputType)(f, g);
401 }
402 
403 /// Function to Either.
404 alias LeftEither(A, B) = RealFunction!(left!(B, A));
405 
406 /// ditto
407 alias RightEither(A, B) = RealFunction!(right!(A, B));
408 
409 /// Either!(, B) functor at A.
410 Either!(A, B) left(B, A)(A a)
411 {
412 	Either!(A, B) x;
413 	x = a;
414 	return x;
415 }
416 
417 /// Either!(A, ) functor at B.
418 Either!(A, B) right(A, B)(B b)
419 {
420 	Either!(A, B) x;
421 	x = b;
422 	return x;
423 }
424 
425 Either!A left(A)(A a)
426 {
427 	Either!A x;
428 	x = Left!A(a);
429 	return x;
430 }
431 
432 Either!A right(A)(A a)
433 {
434 	Either!A x;
435 	x = Right!A(a);
436 	return x;
437 }
438 
439 unittest
440 {
441 	auto a = 1.left;
442 	auto b = 1.right;
443 	auto c = int(1).left!string;
444 	auto d = int(1).right!string;
445 }
446 
447 
448 /// Function from and to Either.
449 auto eitherEither(F, G)(F f, G g)
450 {
451 	return eitherFunction(
452 		f.compose(LeftEither!(F.OutputType, G.OutputType).get),
453 		g.compose(RightEither!(F.OutputType, G.OutputType).get));
454 }
455 
456 /// Tuple of functions, which returns a Tuple.
457 class FunctionTuple(A, B, C) : Function!(A, Tuple!(B, C))
458 {
459 	Function!(A, B) f;
460 	Function!(A, C) g;
461 	this (Function!(A, B) f, Function!(A, C) g)
462 	{
463 		this.f = f;
464 		this.g = g;
465 	}
466 	override Tuple!(B, C) opCall(A x)
467 	{
468 		return tuple(f(x), g(x));
469 	}
470 }
471 
472 /// ditto
473 auto functionTuple(F, G)(F f, G g)
474 	if (is (F.InputType == G.InputType))
475 {
476 	return new FunctionTuple!(F.InputType, F.OutputType, G.OutputType)(f, g);
477 }
478 
479 /// Function from Tuple.
480 auto tupleLeft(T)(T x)
481 {
482 	return x[0];
483 }
484 
485 /// ditto
486 auto tupleRight(T)(T x)
487 {
488 	return x[1];
489 }
490 
491 /// ditto
492 alias TupleLeft(A, B) = RealFunction!(tupleLeft!(Tuple!(A, B)));
493 
494 /// ditto
495 alias TupleRight(A, B) = RealFunction!(tupleRight!(Tuple!(A, B)));
496 
497 /// Function from and to Tuple.
498 auto tupleTuple(F, G)(F f, G g)
499 {
500 	return functionTuple(
501 		TupleLeft!(F.InputType, G.InputType).get.compose(f),
502 		TupleRight!(F.InputType, G.InputType).get.compose(g));
503 }
504 
505 /// Function from Tuple of Maybe to Maybe of Tuple.
506 auto maybeTuple(TM)(TM x)
507 {
508 	if (x[0].isNull || x[1].isNull)
509 		return nothing!(Tuple!(typeof (x[0].get), typeof (x[1].get)));
510 	return just(x[0].get.tuple(x[1].get));
511 }
512 
513 /// ditto
514 alias MaybeTuple(A, B) = RealFunction!(maybeTuple!(Tuple!(Maybe!A, Maybe!B)));
515 
516 /// Returns the function which swaps the components of the given tuple.
517 auto swapper(A, B)()
518 {
519 	return TupleRight!(A, B).get.functionTuple(TupleLeft!(A, B).get);
520 }
521 
522 /// Compose with swapper.
523 auto swapResult(F)(F f)
524 {
525 	return f.compose(swapper!(F.OutputType.Types[0], F.OutputType.Types[1])());
526 }
527 
528 ///
529 unittest
530 {
531 	auto x = new Maybe!int[4];
532 	auto y = new Maybe!int[4];
533 	auto z = new Maybe!(Tuple!(int, int))[4];
534 	x[0] = 2; x[1] = 3;
535 	y[0] = 5, y[2] = 7;
536 	z[0] = 5.tuple(2);
537 	auto p = IdentityFunction!(Tuple!(Maybe!int, Maybe!int)).get
538 	.swapResult.compose(MaybeTuple!(int, int).get);
539 	foreach (i; 0..4)
540 		assert (p(x[i].tuple(y[i])).maybeEqual(z[i]));
541 }
542 
543 /// (a -> b) -> (a -> (b, a))
544 auto functionTupleIdentity(F)(F f)
545 {
546 	return f.functionTuple(IdentityFunction!(F.InputType).get);
547 }
548 
549 /// (a -> b) -> ((a, c) -> (b, c))
550 auto tupleTupleIdentity(B, F)(F f)
551 {
552 	return f.tupleTuple(IdentityFunction!B.get);
553 }
554 
555 /// (a -> b) -> (a|b -> b)
556 auto eitherFunctionIdentity(F)(F f)
557 {
558 	return f.eitherFunction(IdentityFunction!(F.OutputType).get);
559 }
560 
561 /// (a -> b) -> (a|c -> b|c)
562 auto eitherEitherIdentity(B, F)(F f)
563 {
564 	return f.eitherEither(IdentityFunction!B.get);
565 }
566 
567 ///
568 unittest
569 {
570 	static class TestedFunction : Function!(int, string)
571 	{
572 		override string opCall(int x)
573 		{
574 			import std.math, std.conv;
575 			return sqrt(real(1) + x * x).to!string;
576 		}
577 		mixin Singleton;
578 	}
579 	auto t = TestedFunction.get;
580 	auto
581 		t0 = t.functionTupleIdentity,
582 		t1 = t.tupleTupleIdentity!(int[]),
583 		t2 = t.eitherFunctionIdentity,
584 		t3 = t.eitherEitherIdentity!(int[]);
585 	static assert (is (typeof (t0) : Function!(int, Tuple!(string, int))));
586 	static assert (is (typeof (t1) : Function!(Tuple!(int, int[]), Tuple!(string, int[]))));
587 	static assert (is (typeof (t2) : Function!(Either!(int, string), string)));
588 	static assert (is (typeof (t3) : Function!(Either!(int, int[]), Either!(string, int[]))));
589 }
590 
591 /// Either of functions, which returns an Either.
592 class FunctionEither(A, B, C) : Function!(A, Either!(B, C))
593 {
594 	Either!(Function!(A, B), Function!(A, C)) f;
595 	this (Either!(Function!(A, B), Function!(A, C)) f)
596 	{
597 		this.f = f;
598 	}
599 	this (Function!(A, B) f)
600 	{
601 		this.f = f;
602 	}
603 	this (Function!(A, C) f)
604 	{
605 		this.f = f;
606 	}
607 	override Either!(B, C) opCall(A x)
608 	{
609 		if (!f.which)
610 			return f.a()(x).left!C;
611 		else
612 			return f.b()(x).right!B;
613 	}
614 }
615 
616 /// ditto
617 auto functionEitherLeft(C, F)(F f)
618 {
619 	static if (is (F : Function!(A, B), A, B))
620 		return new FunctionEither!(A, B, C)(f);
621 	else static assert (false);
622 }
623 
624 /// ditto
625 auto functionEitherRight(B, F)(F f)
626 {
627 	static if (is (F : Function!(A, C), A, C))
628 		return new FunctionEither!(A, B, C)(f);
629 	else static assert (false);
630 }
631 
632 ///
633 unittest
634 {
635 	static real lreal(int x)
636 	{
637 		import std.math;
638 		return PI * x;
639 	}
640 	static string rstring(int x)
641 	{
642 		import std.conv;
643 		return x.to!string;
644 	}
645 	auto fl = RealFunction!lreal.get.functionEitherLeft!string;
646 	auto fr = RealFunction!rstring.get.functionEitherRight!real;
647 	static assert (is (typeof (fl) == typeof (fr)));
648 }
649 
650 /// Either of functions, which takes a Tuple.
651 class TupleFunction(A, B, C) : Function!(Tuple!(A, B), C)
652 {
653 	Either!(Function!(A, C), Function!(B, C)) f;
654 	this (Either!(Function!(A, C), Function!(B, C)) f)
655 	{
656 		this.f = f;
657 	}
658 	this (Function!(A, C) f)
659 	{
660 		this.f = f;
661 	}
662 	this (Function!(B, C) f)
663 	{
664 		this.f = f;
665 	}
666 	override C opCall(Tuple!(A, B) x)
667 	{
668 		if (!f.which)
669 			return f.a()(x[0]);
670 		else
671 			return f.b()(x[1]);
672 	}
673 }
674 
675 /// ditto
676 auto leftTupleFunction(B, F)(F f)
677 {
678 	return new TupleFunction!(F.InputType, B, F.OutputType)(f);
679 }
680 
681 /// ditto
682 auto rightTupleFunction(A, F)(F f)
683 {
684 	return new TupleFunction!(A, F.InputType, F.OutputType)(f);
685 }
686 
687 ///
688 unittest
689 {
690 	static string cts(char x)
691 	{
692 		import std.conv : to;
693 		return x.to!string;
694 	}
695 	static string rts(real x)
696 	{
697 		import std.conv : to;
698 		return x.to!string;
699 	}
700 	auto l = RealFunction!cts.get.leftTupleFunction!real;
701 	auto r = RealFunction!rts.get.rightTupleFunction!char;
702 	static assert (is (typeof (l) == typeof (r)));
703 }
704 
705 /// Takues an array of functions and return a function to array.
706 class FunctionArray(A, B) : Function!(A, B[])
707 {
708 	Function!(A, B)[] fs;
709 	this (Function!(A, B)[] fs)
710 	{
711 		this.fs = fs;
712 	}
713 	override B[] opCall(A x)
714 	{
715 		B[] ret;
716 		foreach (f; fs)
717 			ret ~= f(x);
718 		return ret;
719 	}
720 }
721 
722 /// ditto
723 auto functionArray(F)(F[] fs)
724 {
725 	return new FunctionArray!(F.InputType, F.OutputType)(fs);
726 }
727 
728 /// Map function for Array.
729 class ArrayMap(A, B) : Function!(A[], B[])
730 {
731 	Function!(A, B) f;
732 	this (Function!(A, B) f)
733 	{
734 		this.f = f;
735 	}
736 	override B[] opCall(A[] xs)
737 	{
738 		B[] ret;
739 		foreach (x; xs)
740 			ret ~= f(x);
741 		return ret;
742 	}
743 }
744 
745 /// ditto
746 auto arrayMap(F)(F f)
747 {
748 	return new ArrayMap!(F.InputType, F.OutputType)(f);
749 }
750 
751 /// Bind function for Array.
752 class ArrayBind(A, B) : Function!(A[], B[])
753 {
754 	Function!(A, B[]) f;
755 	this (Function!(A, B[]) f)
756 	{
757 		this.f = f;
758 	}
759 	override B[] opCall(A[] xs)
760 	{
761 		B[] ret;
762 		foreach (x; xs)
763 			ret ~= f(x);
764 		return ret;
765 	}
766 }
767 
768 /// ditto
769 auto arrayBind(F)(F f)
770 {
771 	return new ArrayBind!(F.InputType, ElementType!(F.OutputType));
772 }
773 
774 /// Return function for Array.
775 auto arrayOnly(A)(A x)
776 {
777 	return [x];
778 }
779 /// ditto
780 alias arrayReturn(A) = arrayOnly!A;
781 /// ditto
782 alias ArrayReturn(A) = RealFunction!(arrayReturn!A);
783 
784 /// Function from Array to void can be constructed from a Function to void.
785 class ArraySink(A) : Function!(A[], void)
786 {
787 	Function!(A, void) sink;
788 	this (Function!(A, void) sink)
789 	{
790 		this.sink = sink;
791 	}
792 	override void opCall(A[] xs)
793 	{
794 		foreach (x; xs)
795 			sink(x);
796 	}
797 }
798 
799 /// ditto
800 auto arraySink(S)(S sink)
801 	if (is (S : Function!(A, void), A))
802 {
803 	return new ArraySink!(S.InputType)(sink);
804 }
805 
806 ///
807 unittest
808 {
809 	import std.stdio, std.range, std.array;
810 	RealFunction!(writeln!int).get.arraySink()(10.iota.array);
811 }
812 
813 /// Take an array of functions and return a function from and to array.
814 class ArrayArray(A, B) : Function!(A[], B[])
815 {
816 	Function!(A, B)[] fs;
817 	this (Function!(A, B)[] fs)
818 	{
819 		this.fs = fs;
820 	}
821 	@property size_t length()
822 	{
823 		return fs.length;
824 	}
825 	override B[] opCall(A[] xs)
826 	in
827 	{
828 		assert (length == xs.length);
829 	}
830 	body
831 	{
832 		import std.range : zip;
833 		B[] ret;
834 		foreach (fx; fs.zip(xs))
835 			ret ~= fx[0](fx[1]);
836 		return ret;
837 	}
838 }
839 
840 /// ditto
841 auto arrayArray(FS)(FS fs)
842 {
843 	import std.range : ElementType;
844 	return new ArrayArray!(ElementType!FS.InputType, ElementType!FS.OutputType)(fs);
845 }
846 
847 ///
848 unittest
849 {
850 	static class Adder : Function!(int, int)
851 	{
852 		int added;
853 		this (int added)
854 		{
855 			this.added = added;
856 		}
857 		override int opCall(int x)
858 		{
859 			return x + added;
860 		}
861 	}
862 	import std.range : iota;
863 	import std.array : array;
864 	Function!(int, int)[] adders;
865 	foreach_reverse (i; 0..5)
866 		adders ~= new Adder(i + 1);
867 	assert (adders.arrayArray()(5.iota.array) == [5, 5, 5, 5, 5]);
868 }
869 
870 /// Singleton pattern.
871 mixin template Singleton(Flag!"hideConstructor" hideConstructor = Yes.hideConstructor)
872 {
873 	static typeof (this) get()
874 	{
875 		static typeof (this) instance;
876 		if (instance is null)
877 			return instance = new typeof (this)();
878 		return instance;
879 	}
880 	static if (hideConstructor)
881 	private this ()
882 	{
883 	}
884 }
885 
886 debug
887 {
888 	class Printer(T) : Function!(T, void)
889 	{
890 		override void opCall(T x)
891 		{
892 			import std.stdio;
893 			writeln(x);
894 		}
895 		mixin Singleton;
896 	}
897 	auto autoPrint(F)(F f)
898 	{
899 		return f.compose(Printer!(F.OutputType).get);
900 	}
901 	auto autoPrintJustOnly(F)(F f)
902 	{
903 		static if (is (F.OutputType : Maybe!B, B))
904 			return f.compose(Printer!B.get.maybeSink);
905 		else static assert (false);
906 	}
907 }
908 
909 version (unittest)
910 {
911 	T triple(T)(T x)
912 	{
913 		return x * 3;
914 	}
915 	T increment(T)(T x)
916 	{
917 		return x + 1;
918 	}
919 	Maybe!T collatz(T)(T x)
920 	{
921 		if (x <= 1)
922 			return nothing!T;
923 		if (x & 1)
924 			return just(x.triple.increment);
925 		return just(x / 2);
926 	}
927 	bool maybeEqual(T)(Maybe!T x, Maybe!T y)
928 	{
929 		if (x.isNull || y.isNull)
930 			return x.isNull && y.isNull;
931 		return x.get == y.get;
932 	}
933 }
934 
935 unittest
936 {
937 	import std.stdio;
938 	stderr.writeln("unittest passed!");
939 }