非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

自由モノイドのイテレーター(31)

自由モノイドプログラミング言語の作成(MonIter バージョン1.2 仕様(15))

有限または無限の自由モノイドのクラス(FreeMonoid<T>)

FreeMonoid<T> は IEnumerable<T> を実装するクラスとします。IEnumerable<T> を実装すると foreach で使うことができます。IEnumerable<T> を実装するにはメソッド

  • public IEnumerator<T> GetEnumerator()
  • IEnumerator IEnumerable.GetEnumerator()

を実装する必要があります。このクラス内部では

        private IEnumerable<T> elements;

を保持していてこれらのメソッドでは elements.GetEnumerator() を返却します。内部データ elements は

  • public static FreeMonoid Unit(T element)

で作成されると一つの要素からなるリストであり

  • public static FreeMonoid operator &(FreeMonoid mon1, FreeMonoid mon2)
  • public static FreeMonoid operator &(T n1, FreeMonoid mon2)

で作成されると二つのデータを連結したものとなります。

Collect は Expression の Eval メソッドで使います。

ZipWith、Tail は Function の Eval メソッドで使います。

    /// <summary>
    /// 有限または無限の自由モノイドのクラス
    /// </summary>
    /// <typeparam name="T">生成元の型</typeparam>
    internal class FreeMonoid<T> : IEnumerable<T>
    {
        /// <summary>
        /// 有限または無限の生成元の列
        /// </summary>
        private IEnumerable<T> elements;
        public FreeMonoid(IEnumerable<T> enumobj)
        {
            elements = enumobj;
        }
        /// <summary>
        /// IEnumerable 実装のために必要なイテレーターを取得するメソッド
        /// </summary>
        /// <returns>IEnumerable のイテレーター</returns>
        public IEnumerator<T> GetEnumerator()
        {
            return elements.GetEnumerator();
        }
        /// <summary>
        /// IEnumerable 実装のために必要なイテレーターを取得するメソッド
        /// </summary>
        /// <returns>IEnumerable のイテレーター</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        /// <summary>
        /// 任意の個数の自由モノイドの元の積
        /// </summary>
        /// <param name="ms">任意の個数の自由モノイドの元</param>
        /// <returns>任意の個数の自由モノイドの元の積</returns>
        public static FreeMonoid<T> Collect(IEnumerable<FreeMonoid<T>> ms)
        {
            IEnumerable<T> CollectEnum(IEnumerable<FreeMonoid<T>> ms)
            {
                foreach (FreeMonoid<T> m in ms)
                {
                    foreach (T e in m)
                    {
                        yield return e;
                    }
                }
            }
            return new FreeMonoid<T>(CollectEnum(ms));
        }
        /// <summary>
        /// 自由モノイドの元の積
        /// </summary>
        /// <param name="mon1">第一の演算数(自由モノイドの元)</param>
        /// <param name="mon2">第二の演算数(自由モノイドの元)</param>
        /// <returns>自由モノイドの元の積</returns>
        public static FreeMonoid<T> operator &(FreeMonoid<T> mon1, FreeMonoid<T> mon2)
        {
            return new FreeMonoid<T>(mon1.Concat(mon2));
        }
        /// <summary>
        /// 自由モノイドの元の積(生成元と自由モノイドの元の積)
        /// </summary>
        /// <param name="n1">第一の演算数(生成元)</param>
        /// <param name="mon2">第二の演算数(自由モノイドの元)</param>
        /// <returns>自由モノイドの元の積</returns>
        public static FreeMonoid<T> operator &(T n1, FreeMonoid<T> mon2)
        {
            return new FreeMonoid<T>(FreeMonoid<T>.Unit(n1).Concat(mon2));
        }
        /// <summary>
        /// 一つの生成元からなる自由モノイドの元
        /// </summary>
        /// <param name="element">生成元</param>
        /// <returns>一つの生成元からなる自由モノイドの元</returns>
        public static FreeMonoid<T> Unit(T element)
        {
            return new FreeMonoid<T>(new List<T> { element });
        }
        /// <summary>
        /// 自由モノイドの単位元
        /// </summary>
        public static FreeMonoid<T> Zero
        {
            get
            {
                return new FreeMonoid<T>(new List<T> { });
            }
        }
        /// <summary>
        /// 自由モノイドの元の各項と第二の自由モノイドの元の各項に演算を施した結果を項とする自由モノイドの元
        /// </summary>
        /// <param name="mon2">第二の自由モノイドの元</param>
        /// <param name="func">演算</param>
        /// <returns>結果の自由モノイドの元</returns>
        public FreeMonoid<T> ZipWith(FreeMonoid<T> mon2, Func<T, T, T> func)
        {
            return new FreeMonoid<T>(this.Zip(mon2, func));
        }
        /// <summary>
        /// 自由モノイドの元の最初の項を取り除いた自由モノイドの元
        /// </summary>
        /// <returns>自由モノイドの元の最初の項を取り除いた自由モノイドの元</returns>
        public FreeMonoid<T> Tail()
        {
            return new FreeMonoid<T>(this.Skip(1));
        }
    }