All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kynthus.hatalib.argparse.instance.ParserInstances0.scala Maven / Gradle / Ivy

The newest version!
package org.kynthus.hatalib.argparse.instance

import org.kynthus.hatalib.argparse.concept._
import org.kynthus.hatalib.core.concept.{ResultCategory, Run}
import org.kynthus.hatalib.core.syntax.BiNaturalTransformationSyntax.BiNaturalTransformationOps
import org.kynthus.hatalib.core.syntax.TagSyntax.TagOps
import scalaz.syntax.applicative.ApplicativeIdV
import scalaz.syntax.std.function2.ToFunction2Ops
import scalaz.syntax.tag.ToTagOps
import scalaz.{@@, Applicative, \/, ~~>}
import scopt.{OParser, OParserBuilder, Read}
import shapeless.labelled.FieldType
import shapeless.ops.record.{Remover, Selector, Updater}
import shapeless.record.recordOps
import shapeless.{::, HList, Lazy, Refute, lazily}

import scala.collection.immutable.Queue
import scala.language.higherKinds

/**
 * パーサへの各種設定を行う型クラスインスタンスの第1候補です。
 *
 * @author Kynthus Auoeau
 * @since 1.0.0
 * @version 1.0.0
 */
private[instance] trait ParserInstances0 extends Any {

  /**
   * 構築中の情報へ新しい型に対応したオプションを付与します。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam NewInput         パーサの新しい型
   * @tparam InsertingParser  新しい型に対応したオプションを付与する型
   * @tparam InsertedParser   新しい型に対応したオプションを付与した型
   * @tparam InsertedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ新しい型に対応したオプションを付与する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def InsertElementParser[
    Input,
    Instance,
    NewInput: Read,
    InsertingParser <: HList,
    InsertedParser <: HList,
    InsertedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[InsertedCategory] @@ Run.type,
     applicative: Applicative[InsertedCategory],
     currentUpdater: Updater.Aux[
       InsertingParser,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       InsertedParser
     ],
     currentNotExist: Refute[
       Selector[
         InsertingParser,
         ParserCurrent.T
       ]
     ]
   ): ElementParser.Aux[
    InsertingParser @@ (Input @@ Instance),
    NewInput,
    Instance,
    InsertedCategory[InsertedParser @@ (NewInput @@ Instance)]
  ] = ParserInstances0.InsertElementParser

  /**
   * 構築中の情報へ型を持たないオプションを付与します。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
   * @tparam UnusedInput      パーサの現在値の型(未使用)
   * @tparam Instance         現在の初期値の型
   * @tparam InsertingParser  型を持たないオプションを付与する型
   * @tparam InsertedParser   型を持たないオプションを付与した型
   * @tparam InsertedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ型を持たないオプションを付与する型クラスインスタンス。
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def InsertUnitParser[
    UnusedInput,
    Instance,
    InsertingParser <: HList,
    InsertedParser <: HList,
    InsertedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[InsertedCategory] @@ Run.type,
     applicative: Applicative[InsertedCategory],
     currentUpdater: Updater.Aux[
       InsertingParser,
       FieldType[
         ParserCurrent.T,
         OParser[Unit, Instance]
       ],
       InsertedParser
     ],
     currentNotExist: Refute[
       Selector[
         InsertingParser,
         ParserCurrent.T
       ]
     ]
   ): UnitParser.Aux[
    InsertingParser @@ (UnusedInput @@ Instance),
    Instance,
    InsertedCategory[InsertedParser @@ (Unit @@ Instance)]
  ] = ParserInstances0.InsertUnitParser

  /**
   * 構築中の情報へ新しい型に対応したオプションを追加します。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentRemover  構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param decidedSelector 構築中の情報に決定済みパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param decidedUpdater  構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam NewInput        パーサの新しい型
   * @tparam UpdatingParser  新しい型に対応したオプションを追加する型
   * @tparam RemovedCurrent  現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent  現在設定中のパーサを新しい型に対応したオプションで設定しなおした型
   * @tparam UpdatedDecided  決定済みパーサを更新した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ新しい型に対応したオプションを追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def UpdateElementParser[
    Input,
    Instance,
    NewInput: Read,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedCurrent,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       UpdatedCurrent
     ],
     decidedUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ElementParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    NewInput,
    Instance,
    UpdatedCategory[UpdatedDecided @@ (NewInput @@ Instance)]
  ] = ParserInstances0.UpdateElementParser

  /**
   * 構築中の情報へ型を持たないオプションを追加します。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentRemover  構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param decidedSelector 構築中の情報に決定済みパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param decidedUpdater  構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam UpdatingParser  型を持たないオプションを追加する型
   * @tparam RemovedCurrent  現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent  現在設定中のパーサを型を持たないオプションで設定しなおした型
   * @tparam UpdatedDecided  決定済みパーサを更新した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ型を持たないオプションを追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def UpdateUnitParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedCurrent,
       FieldType[
         ParserCurrent.T,
         OParser[Unit, Instance]
       ],
       UpdatedCurrent
     ],
     decidedUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): UnitParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    Instance,
    UpdatedCategory[UpdatedDecided @@ (Unit @@ Instance)]
  ] = ParserInstances0.UpdateUnitParser

  /**
   * 構築中の情報のうちオプションに対する詳細設定を追加します。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentSelector 構築後の情報に現在設定中のパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam UpdatingParser  詳細設定を追加する型
   * @tparam UpdatedParser   詳細設定を追加した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報のうちオプションに対する詳細設定を追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def UpdateConfigParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    UpdatedParser <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentSelector: Selector.Aux[
       UpdatingParser,
       ParserCurrent.T,
       OParser[Input, Instance]
     ],
     currentUpdater: Updater.Aux[
       UpdatingParser,
       FieldType[
         ParserCurrent.T,
         OParser[Input, Instance]
       ],
       UpdatedParser
     ]
   ): ConfigParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    Input,
    Instance,
    UpdatedCategory[UpdatedParser @@ (Input @@ Instance)]
  ] = ParserInstances0.UpdateConfigParser

  /**
   * 構築中の情報を子パーサへ分岐させます。
   *
   * @param runCategory      動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative      構築中の情報をラップ可能なことを保証する
   * @param currentRemover   構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param hierarchyRemover 構築中の情報からパーサ階層を削除できることを保証する
   * @param decidedSelector  構築中の情報に決定済みパーサが存在することを保証する
   * @param hierarchyUpdater 構築中の情報が持つパーサ階層を更新できることを保証する
   * @param decidedUpdater   構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam UpdatingParser   子パーサへの分岐を行う型
   * @tparam ExistHierarchy   現在のパーサ階層の型
   * @tparam RemovedCurrent   構築中の情報から現在設定中のパーサを削除した後の型
   * @tparam RemovedHierarchy 構築中の情報からパーサ階層を削除した後の型
   * @tparam UpdatedHierarchy パーサ階層を更新した後の型
   * @tparam UpdatedDecided   決定済みパーサを更新した後の型
   * @tparam UpdatedCategory  構築中の情報をラップする型
   * @return 構築中の情報を子パーサへ分岐させる型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def UpdateChildrenParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    ExistHierarchy <: HList,
    RemovedCurrent <: HList,
    RemovedHierarchy <: HList,
    UpdatedHierarchy <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     hierarchyRemover: Remover.Aux[
       RemovedCurrent,
       ParserHierarchy.T,
       (ExistHierarchy, RemovedHierarchy)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     hierarchyUpdater: Updater.Aux[
       RemovedHierarchy,
       FieldType[
         ParserHierarchy.T,
         OParser[Input, Instance] :: ExistHierarchy
       ],
       UpdatedHierarchy
     ],
     decidedUpdater: Updater.Aux[
       UpdatedHierarchy,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ChildrenParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    UpdatedCategory[UpdatedDecided @@ (Input @@ Instance)]
  ] = ParserInstances0.UpdateChildrenParser

  /**
   * 構築中の情報を親パーサへ合流させます。
   *
   * @param runCategory          動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative          構築中の情報をラップ可能なことを保証する
   * @param currentRemover       構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param currentUpdater       構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param lazyHierarchyRemover 構築中の情報からパーサ階層を削除できることを保証する(再帰的なので遅延)
   * @param hierarchyUpdater     構築中の情報が持つパーサ階層を更新できることを保証する
   * @param decidedSelector      構築中の情報に決定済みパーサが存在することを保証する
   * @param decidedUpdater       構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam NewInput         親パーサへの合流後の現在値の型
   * @tparam UpdatingParser   親パーサへの合流を行う型
   * @tparam RemovedCurrent   構築中の情報から現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent   現在設定中のパーサを更新した後の型
   * @tparam TailHierarchy    パーサ階層の2番目以降の型
   * @tparam RemovedHierarchy 構築中の情報からパーサ階層を削除した後の型
   * @tparam UpdatedHierarchy パーサ階層を更新した後の型
   * @tparam UpdatedDecided   決定済みパーサを更新した後の型
   * @tparam UpdatedCategory  構築中の情報をラップする型
   * @return 構築中の情報を親パーサへ合流させる型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  implicit final def UpdateParentParser[
    Input,
    Instance,
    NewInput,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    TailHierarchy <: HList,
    RemovedHierarchy <: HList,
    UpdatedHierarchy <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     lazyHierarchyRemover: Lazy[
       Remover.Aux[
         RemovedCurrent,
         ParserHierarchy.T,
         (OParser[NewInput, Instance] :: TailHierarchy, RemovedHierarchy)
       ]
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedHierarchy,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       UpdatedCurrent
     ],
     hierarchyUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserHierarchy.T,
         TailHierarchy
       ],
       UpdatedHierarchy
     ],
     decidedUpdater: Updater.Aux[
       UpdatedHierarchy,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ParentParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    UpdatedCategory[UpdatedDecided @@ (NewInput @@ Instance)]
  ] = ParserInstances0.UpdateParentParser

}

/**
 * パーサへの各種設定を行う型クラスインスタンスの第1候補を内部的に定義します。
 *
 * @author Kynthus Auoeau
 * @since 1.0.0
 * @version 1.0.0
 */
private object ParserInstances0 extends AnyRef {

  /**
   * 構築中の情報へ新しい型に対応したオプションを付与します(内部)。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam NewInput         パーサの新しい型
   * @tparam InsertingParser  新しい型に対応したオプションを付与する型
   * @tparam InsertedParser   新しい型に対応したオプションを付与した型
   * @tparam InsertedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ新しい型に対応したオプションを付与する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def InsertElementParser[
    Input,
    Instance,
    NewInput: Read,
    InsertingParser <: HList,
    InsertedParser <: HList,
    InsertedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[InsertedCategory] @@ Run.type,
     applicative: Applicative[InsertedCategory],
     currentUpdater: Updater.Aux[
       InsertingParser,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       InsertedParser
     ],
     currentNotExist: Refute[
       Selector[
         InsertingParser,
         ParserCurrent.T
       ]
     ]
   ): ElementParser.Aux[
    InsertingParser @@ (Input @@ Instance),
    NewInput,
    Instance,
    InsertedCategory[InsertedParser @@ (NewInput @@ Instance)]
  ] = new ElementParser[InsertingParser @@ (Input @@ Instance)] {

    /**
     * 初期値の型に対するパーサを構築する際に使用します。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] val builder: OParserBuilder[super.Struct] = OParser.builder

    /**
     * 新しいオプションに対応する型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Member = NewInput

    /**
     * 各オプションの初期値を持つ型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Struct = Instance

    /**
     * 新しい型に対応したオプションを付与した後の型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = InsertedCategory[InsertedParser @@ (NewInput @@ super.Struct)]

    /**
     * パーサに設定したオプションをまとめて追加します。
     *
     * @param derived オプションの追加先
     * @param parser  追加するオプション
     * @return 現在の型を更新し、オプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def apply
    (
      derived: => InsertingParser @@ (Input @@ super.Struct),
      parser: OParser[super.Member, super.Struct]
    ): super.Result = this (derived) = parser

    /**
     * 単独の位置引数を追加します。
     *
     * @param derived オプションの追加先
     * @param name    位置引数名
     * @return 現在の型を更新し、位置引数を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def arg
    (
      derived: => InsertingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.arg[super.Member](name)

    /**
     * 単独のオプション付き引数を追加します。
     *
     * @param derived オプションの追加先
     * @param name    オプション名
     * @return 現在の型を更新し、オプション付き引数を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def opt
    (
      derived: => InsertingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.opt[super.Member](name)

    /**
     * 構築中の情報へ新しい型に対応したオプションを付与した結果を返します。
     *
     * @param derived 構築中の情報を持つ値
     * @param parser  新しい型に対応したオプション
     * @return 構築中の情報へ新しい型に対応したオプションを付与した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] def update
    (
      derived: => InsertingParser @@ (Input @@ super.Struct),
      parser: OParser[super.Member, super.Struct]
    ): super.Result = {

      // 構築中の情報からタグを外し、新しい型のオプションを現在設定中のパーサとして追加
      val insertedParser: InsertedParser = derived.unwrap.updated(ParserCurrent, parser)

      // 再度タグ付けして返す
      val result: InsertedParser @@ (NewInput @@ super.Struct) = insertedParser.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報へ型を持たないオプションを付与します(内部)。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
   * @tparam UnusedInput      パーサの現在値の型(未使用)
   * @tparam Instance         現在の初期値の型
   * @tparam InsertingParser  型を持たないオプションを付与する型
   * @tparam InsertedParser   型を持たないオプションを付与した型
   * @tparam InsertedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ型を持たないオプションを付与する型クラスインスタンス。
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def InsertUnitParser[
    UnusedInput,
    Instance,
    InsertingParser <: HList,
    InsertedParser <: HList,
    InsertedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[InsertedCategory] @@ Run.type,
     applicative: Applicative[InsertedCategory],
     currentUpdater: Updater.Aux[
       InsertingParser,
       FieldType[
         ParserCurrent.T,
         OParser[Unit, Instance]
       ],
       InsertedParser
     ],
     currentNotExist: Refute[
       Selector[
         InsertingParser,
         ParserCurrent.T
       ]
     ]
   ): UnitParser.Aux[
    InsertingParser @@ (UnusedInput @@ Instance),
    Instance,
    InsertedCategory[InsertedParser @@ (Unit @@ Instance)]
  ] = new UnitParser[InsertingParser @@ (UnusedInput @@ Instance)] {

    /**
     * 初期値の型に対するパーサを構築する際に使用します。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] val builder: OParserBuilder[super.Struct] = OParser.builder

    /**
     * 各オプションの初期値を持つ型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Struct = Instance

    /**
     * 型を持たないオプションを付与した後の型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = InsertedCategory[InsertedParser @@ (Unit @@ super.Struct)]

    /**
     * プログラム名を設定します。
     *
     * @param derived オプションの追加先
     * @param name    プログラム名
     * @return プログラム名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def programName
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.programName(name)

    /**
     * ヘッダメッセージを設定します。
     *
     * @param derived メッセージの追加先
     * @param message ヘッダメッセージ
     * @return ヘッダメッセージを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def head
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      message: String*
    ): super.Result = this (derived) = this.builder.head(message: _*)

    /**
     * サブコマンドを追加します。
     *
     * @param derived サブコマンドの追加先
     * @param name    サブコマンド名
     * @return サブコマンドを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def cmd
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.cmd(name)

    /**
     * ヘルプ表示用のオプションを追加します。
     *
     * @param derived オプションの追加先
     * @param name    ヘルプ表示用のオプション名
     * @return ヘルプ表示用のオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def help
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.help(name)

    /**
     * バージョン表示用のオプションを追加します。
     *
     * @param derived オプションの追加先
     * @param name    バージョン表示用のオプション名
     * @return バージョン表示用のオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def version
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.version(name)

    /**
     * コマンドの使用方法として表示されるメッセージを追加します。
     *
     * @param derived メッセージの追加先
     * @param message コマンド使用方法のメッセージ
     * @return コマンドの使用方法を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def note
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      message: String
    ): super.Result = this (derived) = this.builder.note(message)

    /**
     * 実際にコマンドから渡されたオプション値を検証します。
     *
     * @param derived       オプションの追加先
     * @param checker       フィールド値に対する、正常・異常の判定処理
     * @param toDisjunction 成功・失敗を表現可能な型から[[scalaz.\/]]へ変換できることを保証する
     * @param toEither      [[scalaz.\/]]から[[scala.Either]]へ変換できることを保証する
     * @tparam UnusedRight    成功を表現する型が持つ右側の型([[scala.Unit]]への変換により破棄)
     * @tparam UnusedCategory 2つの型パラメータを持ち、成功・失敗を表現可能な型
     * @return 検証処理を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def checkConfig[UnusedRight, UnusedCategory[_, _]]
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      checker: super.Struct => UnusedCategory[String, UnusedRight]
    )(implicit
      toDisjunction: UnusedCategory ~~> \/,
      toEither: \/ ~~> Either
    ): super.Result = this (derived) = this.builder.checkConfig {
      checker(_)
        .biTransform
        .map(_ => ())
        .biTransform
    }

    /**
     * 構築中の情報へ型を持たないオプションを付与した結果を返します。
     *
     * @param derived 構築中の情報を持つ値
     * @param parser  型を持たないオプション
     * @return 構築中の情報へ型を持たないオプションを付与した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] def update
    (
      derived: => InsertingParser @@ (UnusedInput @@ super.Struct),
      parser: OParser[Unit, super.Struct]
    ): super.Result = {

      // 構築中の情報からタグを外し、型を持たないオプションを現在設定中のパーサとして追加
      val insertedParser: InsertedParser = derived.unwrap.updated(ParserCurrent, parser)

      // 再度タグ付けして返す
      val result: InsertedParser @@ (Unit @@ super.Struct) = insertedParser.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報へ新しい型に対応したオプションを追加します(内部)。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentRemover  構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param decidedSelector 構築中の情報に決定済みパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param decidedUpdater  構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam NewInput        パーサの新しい型
   * @tparam UpdatingParser  新しい型に対応したオプションを追加する型
   * @tparam RemovedCurrent  現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent  現在設定中のパーサを新しい型に対応したオプションで設定しなおした型
   * @tparam UpdatedDecided  決定済みパーサを更新した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ新しい型に対応したオプションを追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def UpdateElementParser[
    Input,
    Instance,
    NewInput: Read,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedCurrent,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       UpdatedCurrent
     ],
     decidedUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ElementParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    NewInput,
    Instance,
    UpdatedCategory[UpdatedDecided @@ (NewInput @@ Instance)]
  ] = new ElementParser[UpdatingParser @@ (Input @@ Instance)] {

    /**
     * 初期値の型に対するパーサを構築する際に使用します。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] val builder: OParserBuilder[super.Struct] = OParser.builder

    /**
     * 新しいオプションに対応する型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Member = NewInput

    /**
     * 各オプションの初期値を持つ型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Struct = Instance

    /**
     * 新しい型に対応したオプションを追加した後の型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = UpdatedCategory[UpdatedDecided @@ (super.Member @@ super.Struct)]

    /**
     * パーサに設定したオプションをまとめて追加します。
     *
     * @param derived オプションの追加先
     * @param parser  追加するオプション
     * @return 現在の型を更新し、オプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def apply
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      parser: OParser[super.Member, super.Struct]
    ): super.Result = this (derived) = parser

    /**
     * 単独の位置引数を追加します。
     *
     * @param derived オプションの追加先
     * @param name    位置引数名
     * @return 現在の型を更新し、位置引数を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def arg
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.arg[super.Member](name)

    /**
     * 単独のオプション付き引数を追加します。
     *
     * @param derived オプションの追加先
     * @param name    オプション名
     * @return 現在の型を更新し、オプション付き引数を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def opt
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.opt[super.Member](name)

    /**
     * 構築中の情報へ新しい型に対応したオプションを追加した結果を返します。
     *
     * @param derived 構築中の情報を持つ値
     * @param parser  新しい型に対応したオプション
     * @return 構築中の情報へ新しい型に対応したオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] def update
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      parser: OParser[super.Member, super.Struct]
    ): super.Result = {

      // 構築中の情報からタグを外す
      val updatingParser: UpdatingParser = derived.unwrap

      // 現在設定中のパーサを構築中の情報から取得後に削除し、決定済みパーサのキューへ追加
      val (parserCurrent, removedCurrent):
        (OParser[Input, super.Struct], RemovedCurrent) =
        updatingParser.remove(ParserCurrent)

      // 決定済みパーサを取得
      val parserDecided: List[Queue[OParser[_, super.Struct]]] = updatingParser(ParserDecided)

      // 現在設定中のパーサを新しいものへ更新する
      val updatedCurrent: UpdatedCurrent = removedCurrent.updated(ParserCurrent, parser)

      // 決定済みパーサのキューへ追加
      val updatedDecided: UpdatedDecided = updatedCurrent.updated(
        ParserDecided,
        parserDecided.head.enqueue(parserCurrent) :: parserDecided.tail
      )

      // 再度タグ付けして返す
      val result: UpdatedDecided @@ (super.Member @@ super.Struct) = updatedDecided.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報へ型を持たないオプションを追加します(内部)。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentRemover  構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param decidedSelector 構築中の情報に決定済みパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param decidedUpdater  構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam UpdatingParser  型を持たないオプションを追加する型
   * @tparam RemovedCurrent  現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent  現在設定中のパーサを型を持たないオプションで設定しなおした型
   * @tparam UpdatedDecided  決定済みパーサを更新した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報へ型を持たないオプションを追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def UpdateUnitParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedCurrent,
       FieldType[
         ParserCurrent.T,
         OParser[Unit, Instance]
       ],
       UpdatedCurrent
     ],
     decidedUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): UnitParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    Instance,
    UpdatedCategory[UpdatedDecided @@ (Unit @@ Instance)]
  ] = new UnitParser[UpdatingParser @@ (Input @@ Instance)] {

    /**
     * 初期値の型に対するパーサを構築する際に使用します。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] val builder: OParserBuilder[super.Struct] = OParser.builder

    /**
     * 各オプションの初期値を持つ型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Struct = Instance

    /**
     * 型を持たないオプションを追加した後の型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = UpdatedCategory[UpdatedDecided @@ (Unit @@ super.Struct)]

    /**
     * プログラム名を設定します。
     *
     * @param derived オプションの追加先
     * @param name    プログラム名
     * @return プログラム名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def programName
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.programName(name)

    /**
     * ヘッダメッセージを設定します。
     *
     * @param derived メッセージの追加先
     * @param message ヘッダメッセージ
     * @return ヘッダメッセージを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def head
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      message: String*
    ): super.Result = this (derived) = this.builder.head(message: _*)

    /**
     * サブコマンドを追加します。
     *
     * @param derived サブコマンドの追加先
     * @param name    サブコマンド名
     * @return サブコマンドを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def cmd
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.cmd(name)

    /**
     * ヘルプ表示用のオプションを追加します。
     *
     * @param derived オプションの追加先
     * @param name    ヘルプ表示用のオプション名
     * @return ヘルプ表示用のオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def help
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.help(name)

    /**
     * バージョン表示用のオプションを追加します。
     *
     * @param derived オプションの追加先
     * @param name    バージョン表示用のオプション名
     * @return バージョン表示用のオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def version
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      name: String
    ): super.Result = this (derived) = this.builder.version(name)

    /**
     * コマンドの使用方法として表示されるメッセージを追加します。
     *
     * @param derived メッセージの追加先
     * @param message コマンド使用方法のメッセージ
     * @return コマンドの使用方法を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def note
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      message: String
    ): super.Result = this (derived) = this.builder.note(message)

    /**
     * 実際にコマンドから渡されたオプション値を検証します。
     *
     * @param derived       オプションの追加先
     * @param checker       フィールド値に対する、正常・異常の判定処理
     * @param toDisjunction 成功・失敗を表現可能な型から[[scalaz.\/]]へ変換できることを保証する
     * @param toEither      [[scalaz.\/]]から[[scala.Either]]へ変換できることを保証する
     * @tparam UnusedRight    成功を表現する型が持つ右側の型([[scala.Unit]]への変換により破棄)
     * @tparam UnusedCategory 2つの型パラメータを持ち、成功・失敗を表現可能な型
     * @return 検証処理を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def checkConfig[UnusedRight, UnusedCategory[_, _]]
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      checker: super.Struct => UnusedCategory[String, UnusedRight]
    )(
      implicit
      toDisjunction: UnusedCategory ~~> \/,
      toEither: \/ ~~> Either
    ): super.Result = this (derived) = this.builder.checkConfig {
      checker(_)
        .biTransform
        .map(_ => ())
        .biTransform
    }

    /**
     * 構築中の情報へ型を持たないオプションを追加した結果を返します。
     *
     * @param derived 構築中の情報を持つ値
     * @param parser  型を持たないオプション
     * @return 構築中の情報へ型を持たないオプションを追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] def update
    (
      derived: => UpdatingParser @@ (Input @@ super.Struct),
      parser: OParser[Unit, super.Struct]
    ): super.Result = {

      // 構築中の情報からタグを外す
      val updatingParser: UpdatingParser = derived.unwrap

      // 現在設定中のパーサを構築中の情報から取得後に削除し、決定済みパーサのキューへ追加
      val (parserCurrent, removedCurrent):
        (OParser[Input, super.Struct], RemovedCurrent) =
        updatingParser.remove(ParserCurrent)

      // 決定済みパーサを取得
      val parserDecided: List[Queue[OParser[_, super.Struct]]] = updatingParser(ParserDecided)

      // 現在設定中のパーサを新しいものへ更新する
      val updatedCurrent: UpdatedCurrent = removedCurrent.updated(ParserCurrent, parser)

      // 決定済みパーサのキューへ追加
      val updatedDecided: UpdatedDecided = updatedCurrent.updated(
        ParserDecided,
        parserDecided.head.enqueue(parserCurrent) :: parserDecided.tail
      )

      // 再度タグ付けして返す
      val result: UpdatedDecided @@ (Unit @@ super.Struct) = updatedDecided.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報のうちオプションに対する詳細設定を追加します(内部)。
   *
   * @param runCategory     動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative     構築中の情報をラップ可能なことを保証する
   * @param currentSelector 構築後の情報に現在設定中のパーサが存在することを保証する
   * @param currentUpdater  構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @tparam Input           パーサの現在値の型
   * @tparam Instance        現在の初期値の型
   * @tparam UpdatingParser  詳細設定を追加する型
   * @tparam UpdatedParser   詳細設定を追加した型
   * @tparam UpdatedCategory 構築中の情報をラップする型
   * @return 構築中の情報のうちオプションに対する詳細設定を追加する型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def UpdateConfigParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    UpdatedParser <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentSelector: Selector.Aux[
       UpdatingParser,
       ParserCurrent.T,
       OParser[Input, Instance]
     ],
     currentUpdater: Updater.Aux[
       UpdatingParser,
       FieldType[
         ParserCurrent.T,
         OParser[Input, Instance]
       ],
       UpdatedParser
     ]
   ): ConfigParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    Input,
    Instance,
    UpdatedCategory[UpdatedParser @@ (Input @@ Instance)]
  ] = new ConfigParser[UpdatingParser @@ (Input @@ Instance)] {

    /**
     * 現在のオプションに対応する型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Member = Input

    /**
     * 各オプションの初期値を持つ型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Struct = Instance

    /**
     * オプションへ詳細設定を適用した後の型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = UpdatedCategory[UpdatedParser @@ (super.Member @@ super.Struct)]

    /**
     * オプションに対して別名を設定します。
     *
     * @param derived 別名の設定先
     * @param name    オプションの別名
     * @return 別名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def abbr
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      name: String
    ): super.Result = this (derived) = _.abbr(name)

    /**
     * オプションが指定された際に実行する処理を設定します。
     *
     * @param derived  実行する処理の設定先
     * @param function 実行する処理
     * @return 実行する処理を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def action
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      function: (super.Struct, super.Member) => super.Struct
    ): super.Result = this (derived) = _.action(function.flip)

    /**
     * オプションの説明文を設定します。
     *
     * @param derived オプションに対する説明文の設定先
     * @param message オプションに対する説明文
     * @return 説明文を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def text
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      message: String
    ): super.Result = this (derived) = _.text(message)

    /**
     * オプションに最低限必要な引数の数を設定します。
     *
     * @param derived 最低限必要な引数の数の設定先
     * @param occurs  最低限必要な引数の数
     * @return 最低限必要な引数の数を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def minOccurs
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      occurs: Int
    ): super.Result = this (derived) = _.minOccurs(occurs)

    /**
     * オプションに引数をいくつまで指定できるかを設定します。
     *
     * @param derived 引数を最大いくつまで指定できるかの設定先
     * @param occurs  引数の最大数
     * @return 引数の最大数を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def maxOccurs
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      occurs: Int
    ): super.Result = this (derived) = _.maxOccurs(occurs)

    /**
     * オプションを必須扱いにします。
     *
     * @param derived オプションを必須化する設定を行う先
     * @return オプションを必須化した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def required
    (derived: => UpdatingParser @@ (super.Member @@ super.Struct)):
    super.Result = this (derived) = _.required()

    /**
     * オプションを任意(省略可能)にします。
     *
     * @param derived オプションを任意化する設定を行う先
     * @return オプションを任意化した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def optional
    (derived: => UpdatingParser @@ (super.Member @@ super.Struct)):
    super.Result = this (derived) = _.optional()

    /**
     * オプションに対して引数を無制限に指定できるようにします。
     *
     * @param derived 引数を無制限に指定できるよう設定を行う先
     * @return 引数の指定数を無制限とした結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def unbounded
    (derived: => UpdatingParser @@ (super.Member @@ super.Struct)):
    super.Result = this (derived) = _.unbounded()

    /**
     * オプションを隠しオプションにします。
     *
     * @param derived 隠しオプション化の設定先
     * @return 隠しオプション化した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def hidden
    (derived: => UpdatingParser @@ (super.Member @@ super.Struct)):
    super.Result = this (derived) = _.hidden()

    /**
     * オプションのキー名を設定します。
     *
     * @param derived キー名の設定先
     * @param name    キー名
     * @return キー名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def keyName
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      name: String
    ): super.Result = this (derived) = _.keyName(name)

    /**
     * オプションの値名を設定します。
     *
     * @param derived 値名の設定先
     * @param name    値名
     * @return 値名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def valueName
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      name: String
    ): super.Result = this (derived) = _.valueName(name)

    /**
     * オプションのキー名と値名を設定します。
     *
     * @param derived   キー名と値名の設定先
     * @param keyName   キー名
     * @param valueName 値名
     * @return キー名と値名を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def keyValueName
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      keyName: String,
      valueName: String
    ): super.Result = this (derived) = _.keyValueName(keyName, valueName)

    /**
     * 実際にコマンドから渡されたオプション値を検証します。
     *
     * @param derived       検証処理の設定先
     * @param validator     検証処理
     * @param toDisjunction 成功・失敗を表現可能な型から[[scalaz.\/]]へ変換できることを保証する
     * @param toEither      [[scalaz.\/]]から[[scala.Either]]へ変換できることを保証する
     * @tparam UnusedRight    成功を表現する型が持つ右側の型([[scala.Unit]]への変換により破棄)
     * @tparam UnusedCategory 2つの型パラメータを持ち、成功・失敗を表現可能な型
     * @return 検証処理を設定した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def validate[UnusedRight, UnusedCategory[_, _]]
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      validator: super.Member => UnusedCategory[String, UnusedRight]
    )(
      implicit
      toDisjunction: UnusedCategory ~~> \/,
      toEither: \/ ~~> Either
    ): super.Result = this (derived) = _.validate {
      validator(_)
        .biTransform
        .map(_ => ())
        .biTransform
    }

    /**
     * 構築中の情報が持つオプションへ詳細設定を追加した結果を返します。
     *
     * @param derived  現在設定中のオプションを持つ値
     * @param function 詳細設定を追加する処理
     * @return 構築中の情報が持つオプションへ詳細設定を追加した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] def update
    (
      derived: => UpdatingParser @@ (super.Member @@ super.Struct),
      function: OParser[super.Member, super.Struct] => OParser[super.Member, super.Struct]
    ): super.Result = {

      // 構築中の情報からタグを外す
      val updatingParser: UpdatingParser = derived.unwrap

      // 現在設定中のパーサを新しいものへ更新する
      val currentParser: OParser[super.Member, super.Struct] = updatingParser(ParserCurrent)
      val updatedParser: UpdatedParser = updatingParser.replace(ParserCurrent, function(currentParser))

      // 再度タグ付けして返す
      val result: UpdatedParser @@ (super.Member @@ super.Struct) = updatedParser.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報を子パーサへ分岐させます(内部)。
   *
   * @param runCategory      動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative      構築中の情報をラップ可能なことを保証する
   * @param currentRemover   構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param hierarchyRemover 構築中の情報からパーサ階層を削除できることを保証する
   * @param decidedSelector  構築中の情報に決定済みパーサが存在することを保証する
   * @param hierarchyUpdater 構築中の情報が持つパーサ階層を更新できることを保証する
   * @param decidedUpdater   構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam UpdatingParser   子パーサへの分岐を行う型
   * @tparam ExistHierarchy   現在のパーサ階層の型
   * @tparam RemovedCurrent   構築中の情報から現在設定中のパーサを削除した後の型
   * @tparam RemovedHierarchy 構築中の情報からパーサ階層を削除した後の型
   * @tparam UpdatedHierarchy パーサ階層を更新した後の型
   * @tparam UpdatedDecided   決定済みパーサを更新した後の型
   * @tparam UpdatedCategory  構築中の情報をラップする型
   * @return 構築中の情報を子パーサへ分岐させる型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def UpdateChildrenParser[
    Input,
    Instance,
    UpdatingParser <: HList,
    ExistHierarchy <: HList,
    RemovedCurrent <: HList,
    RemovedHierarchy <: HList,
    UpdatedHierarchy <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     hierarchyRemover: Remover.Aux[
       RemovedCurrent,
       ParserHierarchy.T,
       (ExistHierarchy, RemovedHierarchy)
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     hierarchyUpdater: Updater.Aux[
       RemovedHierarchy,
       FieldType[
         ParserHierarchy.T,
         OParser[Input, Instance] :: ExistHierarchy
       ],
       UpdatedHierarchy
     ],
     decidedUpdater: Updater.Aux[
       UpdatedHierarchy,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ChildrenParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    UpdatedCategory[UpdatedDecided @@ (Input @@ Instance)]
  ] = new ChildrenParser[UpdatingParser @@ (Input @@ Instance)] {

    /**
     * 子パーサへの分岐後に返す型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = UpdatedCategory[UpdatedDecided @@ (Input @@ Instance)]

    /**
     * 構築中の情報を子パーサへ分岐させた結果を返します。
     *
     * @param derived 子パーサへ分岐可能な値
     * @return 子パーサへ分岐した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def apply
    (derived: => UpdatingParser @@ (Input @@ Instance)):
    this.Result = {

      // 構築中の情報からタグを外す
      val updatingParser: UpdatingParser = derived.unwrap

      // 現在設定中のパーサとパーサ階層を取得し、いったん情報から削除する
      val (current, removedCurrent):
        (OParser[Input, Instance], RemovedCurrent) =
        updatingParser.remove(ParserCurrent)
      val (hierarchy, removedHierarchy):
        (ExistHierarchy, RemovedHierarchy) =
        removedCurrent.remove(ParserHierarchy)

      // 決定済みパーサを取得する
      val decided: List[Queue[OParser[_, Instance]]] = updatingParser(ParserDecided)

      // 現在設定中のパーサをパーサ階層の先頭へ追加する形で更新する
      val updatedHierarchy: UpdatedHierarchy =
        removedHierarchy.updated(ParserHierarchy, current :: hierarchy)

      // 空のキューを用意し、決定済みパーサの先頭へ追加する
      val empty: Queue[OParser[_, Instance]] = Queue.empty
      val updatedParser: UpdatedDecided = updatedHierarchy.updated(
        ParserDecided,
        empty :: decided
      )

      // 更新結果を再度タグ付けして返す
      val result: UpdatedDecided @@ (Input @@ Instance) = updatedParser.wrap
      result.pure

    }

  }

  /**
   * 構築中の情報を親パーサへ合流させます(内部)。
   *
   * @param runCategory          動作設定を持つ値を格納する型を決定するマーカー
   * @param applicative          構築中の情報をラップ可能なことを保証する
   * @param currentRemover       構築中の情報から現在設定中のパーサを削除できることを保証する
   * @param lazyHierarchyRemover 構築中の情報からパーサ階層を削除できることを保証する(再帰的なので遅延)
   * @param decidedSelector      構築中の情報に決定済みパーサが存在することを保証する
   * @param currentUpdater       構築中の情報が持つ現在設定中のパーサを更新できることを保証する
   * @param hierarchyUpdater     構築中の情報が持つパーサ階層を更新できることを保証する
   * @param decidedUpdater       構築中の情報が持つ決定済みパーサを更新できることを保証する
   * @tparam Input            パーサの現在値の型
   * @tparam Instance         現在の初期値の型
   * @tparam NewInput         親パーサへの合流後の現在値の型
   * @tparam UpdatingParser   親パーサへの合流を行う型
   * @tparam RemovedCurrent   構築中の情報から現在設定中のパーサを削除した後の型
   * @tparam UpdatedCurrent   現在設定中のパーサを更新した後の型
   * @tparam TailHierarchy    パーサ階層の2番目以降の型
   * @tparam RemovedHierarchy 構築中の情報からパーサ階層を削除した後の型
   * @tparam UpdatedHierarchy パーサ階層を更新した後の型
   * @tparam UpdatedDecided   決定済みパーサを更新した後の型
   * @tparam UpdatedCategory  構築中の情報をラップする型
   * @return 構築中の情報を親パーサへ合流させる型クラスインスタンス
   * @author Kynthus Auoeau
   * @since 1.0.0
   * @version 1.0.0
   */
  private final def UpdateParentParser[
    Input,
    Instance,
    NewInput,
    UpdatingParser <: HList,
    RemovedCurrent <: HList,
    UpdatedCurrent <: HList,
    TailHierarchy <: HList,
    RemovedHierarchy <: HList,
    UpdatedHierarchy <: HList,
    UpdatedDecided <: HList,
    UpdatedCategory[_]
  ](
     implicit
     runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
     applicative: Applicative[UpdatedCategory],
     currentRemover: Remover.Aux[
       UpdatingParser,
       ParserCurrent.T,
       (OParser[Input, Instance], RemovedCurrent)
     ],
     lazyHierarchyRemover: Lazy[
       Remover.Aux[
         RemovedCurrent,
         ParserHierarchy.T,
         (OParser[NewInput, Instance] :: TailHierarchy, RemovedHierarchy)
       ]
     ],
     decidedSelector: Selector.Aux[
       UpdatingParser,
       ParserDecided.T,
       List[Queue[OParser[_, Instance]]]
     ],
     currentUpdater: Updater.Aux[
       RemovedHierarchy,
       FieldType[
         ParserCurrent.T,
         OParser[NewInput, Instance]
       ],
       UpdatedCurrent
     ],
     hierarchyUpdater: Updater.Aux[
       UpdatedCurrent,
       FieldType[
         ParserHierarchy.T,
         TailHierarchy
       ],
       UpdatedHierarchy
     ],
     decidedUpdater: Updater.Aux[
       UpdatedHierarchy,
       FieldType[
         ParserDecided.T,
         List[Queue[OParser[_, Instance]]]
       ],
       UpdatedDecided
     ]
   ): ParentParser.Aux[
    UpdatingParser @@ (Input @@ Instance),
    UpdatedCategory[UpdatedDecided @@ (NewInput @@ Instance)]
  ] = new ParentParser[UpdatingParser @@ (Input @@ Instance)] {

    /**
     * 構築中の情報からパーサ階層を削除できることを保証します
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    private[this] implicit val hierarchyRemover: Remover.Aux[
      RemovedCurrent,
      ParserHierarchy.T,
      (OParser[NewInput, Instance] :: TailHierarchy, RemovedHierarchy)
    ] = lazily.apply

    /**
     * 親パーサへの合流後に返す型です。
     *
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override type Result = UpdatedCategory[UpdatedDecided @@ (NewInput @@ Instance)]

    /**
     * 構築中の情報を親パーサへ合流させた結果を返します。
     *
     * @param derived 親パーサへ合流可能な値
     * @return 親パーサへ合流した結果
     * @author Kynthus Auoeau
     * @since 1.0.0
     * @version 1.0.0
     */
    override def apply
    (derived: => UpdatingParser @@ (Input @@ Instance)):
    this.Result = {

      // 構築中の情報からタグを外す
      val updatingParser: UpdatingParser = derived.unwrap

      // 現在設定中のパーサとパーサ階層を取得し、いったん情報から削除する
      val (current, removedCurrent):
        (OParser[Input, Instance], RemovedCurrent) =
        updatingParser.remove(ParserCurrent)
      val (hierarchy, removedHierarchy):
        (OParser[NewInput, Instance] :: TailHierarchy, RemovedHierarchy) =
        removedCurrent.remove(ParserHierarchy)

      // 決定済みパーサを取得する
      val decided: List[Queue[OParser[_, Instance]]] = updatingParser(ParserDecided)

      // 決定済みパーサから取得後、パーサ階層の先頭へ子パーサとして指定し、現在設定中のパーサへ戻す
      val updatedCurrent: UpdatedCurrent = removedHierarchy.updated(
        ParserCurrent,
        hierarchy.head.children(decided.head :+ current: _*)
      )

      // パーサ階層にはもともと保持していた階層から、先頭のみ除いたパーサ階層を設定しなおす
      val updatedHierarchy: UpdatedHierarchy =
        updatedCurrent.updated(ParserHierarchy, hierarchy.tail)

      // 決定済みパーサのうち、先頭のキューは破棄する
      val updatedDecided: UpdatedDecided =
        updatedHierarchy.updated(ParserDecided, decided.tail)

      // 更新結果を再度タグ付けして返す
      val result: UpdatedDecided @@ (NewInput @@ Instance) = updatedDecided.wrap
      result.pure

    }

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy