読者です 読者をやめる 読者になる 読者になる

しーしゃーぷで Either クラス書いてた

NuGet 見てみたら、Monad とかいう興味深い単語があったりしたので、書いてみた:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Prelude.Data {

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="_Left"></typeparam>
    /// <typeparam name="_Right"></typeparam>
    public sealed class Either<_Left, _Right> {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="left"></param>
        private Either(_Left left) {
            this.Left = left;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="right"></param>
        private Either(_Right right) {
            this.Right = right;
        }

        /// <summary>
        /// 
        /// </summary>
        public _Left Left { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public _Right Right { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public bool IsLeft {
            get { return this.which_ == Which.Left; }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsRight {
            get { return this.which_ == Which.Right; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="_A"></typeparam>
        /// <typeparam name="_B"></typeparam>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        public Either<_A, _B> LeftOf<_A, _B>(_A left, _B right = default(_B)) {
            return new Either<_A, _B>( left );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="_A"></typeparam>
        /// <typeparam name="_B"></typeparam>
        /// <param name="right"></param>
        /// <param name="left"></param>
        /// <returns></returns>
        public Either<_A, _B> RightOf<_A, _B>(_B right, _A left = default(_A)) {
            return new Either<_A, _B>( right );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="_A"></typeparam>
        /// <typeparam name="_B"></typeparam>
        /// <typeparam name="_Result"></typeparam>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static _Result Apply<_A, _B, _Result>(Func<_A, _Result> a, Func<_B, _Result> b, Either<_A, _B> value) {
            if ( value.IsRight ) {
                return b( value.Right );
            }
            return a( value.Left );
        }

        /// <summary>
        /// 
        /// </summary>
        private Which which_;
    }
}