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

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

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

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

変数とその値の対応を記憶するためのクラス

変数とその値の対応を記憶する線形リストを保持するクラス(Env<T>)

Env<T> は線形リスト(LinearList<EnvItem<T>>)を保持します。

Env<T> は IEnumerable<EnvItem<T>> を実装するクラスとします。

    /// <summary>
    /// 変数と変数の値の対応を表す「環境」のクラス
    /// </summary>
    /// <typeparam name="T">変数の型</typeparam>
    internal class Env<T> : IEnumerable<EnvItem<T>>
    {
        /// <summary>
        /// 変数と変数の値の対応を保存する線形リスト
        /// </summary>
        private LinearList<EnvItem<T>> list;
        /// <summary>
        /// 変数と変数の値の対応を初期化
        /// </summary>
        public Env()
		{
            list = new LinearList<EnvItem<T>>();
        }
        /// <summary>
        /// IEnumerable 実装のために必要なイテレーターを取得するメソッド
        /// </summary>
        /// <returns>IEnumerable のイテレーター</returns>
        public IEnumerator<EnvItem<T>> GetEnumerator()
        {
            return list.GetEnumerator();
        }
        /// <summary>
        /// IEnumerable 実装のために必要なイテレーターを取得するメソッド
        /// </summary>
        /// <returns>IEnumerable のイテレーター</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        /// <summary>
        /// 変数とその値の対応を追加する
        /// </summary>
        /// <param name="key">変数名</param>
        /// <param name="value"></param>
        /// <returns>変数とその値の対応を追加した「環境」</returns>
        public Env<T> Define(string key, T value)
        {
            Env<T> env = new Env<T>();
            env.list = list.Define(new EnvItem<T>(key, value));
            return env;
        }
        /// <summary>
        /// 複数の変数とその値の対応を追加する
        /// </summary>
        /// <param name="keys">変数のリスト</param>
        /// <param name="values">値のリスト</param>
        /// <returns>変数とその値の対応を追加した「環境」</returns>
        public Env<T> DefineList(IEnumerable<string> keys, IEnumerable<T> values)
        {
            Env<T> env = this;
            foreach ((string key, T value) in keys.Zip(values))
            {
                env = env.Define(key, value);
            }
            return env;
        }
        /// <summary>
        /// 変数の値を取得する
        /// </summary>
        /// <param name="key">変数</param>
        /// <returns>変数の値</returns>
        public T? Value(string key)
        {
            foreach (EnvItem<T> node in this)
            {
                if (node.Key == key)
                {
                    return node.Value;
                }
            }
            return default;
        }
    }
変数と変数の値の組のクラス(EnvItem<T>)
    /// <summary>
    /// 変数と変数の値の対応を保存する線形リストの項目のクラス
    /// </summary>
    /// <typeparam name="T">変数の型</typeparam>
    internal class EnvItem<T>
    {
        /// <summary>
        /// 変数名
        /// </summary>
        private readonly string key;
        /// <summary>
        /// 変数の値
        /// </summary>
        private readonly T value;
        public EnvItem(string key, T value)
        {
            this.key = key;
            this.value = value;
        }
        /// <summary>
        /// 変数名
        /// </summary>
        public string Key => key;
        /// <summary>
        /// 変数の値
        /// </summary>
        public T Value => value;
    }
数値の自由モノイドの元または数値を表すクラス(FreeMonoidUnion)

「数値を生成元とする自由モノイドの元」または「数値」のどちらかを保持するクラス(C# では「どちらか」を表す良い方法がないのでこのクラスがあります)なのですが、現状ではユーザーが定義できる関数はパラメーターの型が数値のものだけなので数値の方しか使われていません。

    /// <summary>
    /// 数値の自由モノイドの元または数値を表すクラス
    /// </summary>
    internal class FreeMonoidUnion
    {
        /// <summary>
        /// 数値のときの値
        /// </summary>
        private readonly Number? domain_value;
        /// <summary>
        /// 数値の自由モノイドの元
        /// </summary>
        private readonly FreeMonoid<int>? monoid_value;
        /// <summary>
        /// 数値の自由モノイドかどうか
        /// </summary>
        private readonly bool ismonoid;
        /// <summary>
        /// 数値のオブジェクトを作成
        /// </summary>
        /// <param name="domain_value">数値</param>
        public FreeMonoidUnion(Number domain_value)
        {
            this.domain_value = domain_value;
            ismonoid = false;
        }
        /// <summary>
        /// 自由モノイドの元のオブジェクトを作成
        /// </summary>
        /// <param name="monoid_value">自由モノイドの元</param>
        public FreeMonoidUnion(FreeMonoid<int> monoid_value)
        {
            this.monoid_value = monoid_value;
            ismonoid = true;
        }
        /// <summary>
        /// 数値の値
        /// </summary>
        internal Number DomainValue => domain_value;
    }