org.kynthus.hatalib.argparse.instance.InitialInstances0.scala Maven / Gradle / Ivy
The newest version!
package org.kynthus.hatalib.argparse.instance
import org.kynthus.hatalib.argparse.concept.Initial
import org.kynthus.hatalib.argparse.syntax.InitialSyntax.InitialOps
import org.kynthus.hatalib.core.concept.{Field, ResultCategory, Run}
import org.kynthus.hatalib.core.syntax.FieldSyntax.FieldOps
import org.kynthus.hatalib.core.syntax.TagSyntax.TagOps
import scalaz.Leibniz.===
import scalaz.syntax.applicative.ApplicativeIdV
import scalaz.syntax.bind.ToBindOps
import scalaz.syntax.tag.ToTagOps
import scalaz.{@@, Applicative, Bind}
import scopt.OParser
import shapeless.labelled.FieldType
import shapeless.ops.record.{Merger, Remover, Selector, Updater}
import shapeless.record.recordOps
import shapeless.{HList, HNil, Refute}
import scala.collection.immutable.Queue
import scala.language.higherKinds
/**
* 初期値を持つフィールドを追加するための型クラスインスタンスの第1候補です。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private[instance] trait InitialInstances0 extends Any {
/**
* 構築中の情報へ初期値を付与します。
*
* @param runCategory 動作設定を持つ値を格納する型を決定するマーカー
* @param applicative 構築中の情報をラップ可能なことを保証する
* @param initialField 初期値として付与する型がフィールドへ変換可能なことを保証する
* @param decidedUpdater 構築中の情報の決定済みパーサを更新できることを保証する
* @param initialUpdater 構築中の情報へ初期値を付与できることを保証する
* @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
* @param initialNotExist 構築中の情報がまだ初期値を持たないことを保証する
* @tparam ConvertingField フィールドへ変換する型
* @tparam ConvertedField フィールドへ変換した型
* @tparam UnusedKeys パーサへのオプション追加時に使用する幽霊型(動作設定時は未使用)
* @tparam InsertingInitial 初期値の付与対象となる型
* @tparam InsertedDecided 決定済みパーサを更新した後の型
* @tparam InsertedInitial 初期値を付与した後の型
* @tparam InsertedCategory 構築中の情報をラップする型
* @return 構築中の情報へ初期値を付与する型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
implicit final def InsertInitial[
ConvertingField,
ConvertedField <: HList,
UnusedKeys,
InsertingInitial <: HList,
InsertedDecided <: HList,
InsertedInitial <: HList,
InsertedCategory[_]
](
implicit
runCategory: ResultCategory[InsertedCategory] @@ Run.type,
applicative: Applicative[InsertedCategory],
initialField: Field.Aux[
ConvertingField,
ConvertedField
],
decidedUpdater: Updater.Aux[
InsertingInitial,
FieldType[
ParserDecided.T,
List[Queue[OParser[_, ConvertedField]]]
],
InsertedDecided
],
initialUpdater: Updater.Aux[
InsertedDecided,
FieldType[
InitialRecord.T,
ConvertedField
],
InsertedInitial
],
currentNotExist: Refute[
Selector[
InsertingInitial,
ParserCurrent.T
]
],
initialNotExist: Refute[
Selector[
InsertingInitial,
InitialRecord.T
]
]
): Initial.Aux[
InsertingInitial @@ UnusedKeys,
ConvertingField,
InsertedCategory[InsertedInitial @@ (Unit @@ ConvertedField)]
] = InitialInstances0.InsertInitial
/**
* 構築中の情報へ初期値を追加します。
*
* @param runCategory 動作設定を持つ値を格納する型を決定するマーカー
* @param applicative 構築中の情報をラップ可能なことを保証する
* @param initialField 初期値として付与する型がフィールドへ変換可能なことを保証する
* @param initialSelector 構築中の情報から設定済みの初期値を取得できることを保証する
* @param initialRemover 構築中の情報から設定済みの初期値を削除できることを保証する
* @param initialMerger 設定済みの初期値と新しい初期値がマージ可能なことを保証する
* @param decidedRemover 構築中の情報から決定済みのパーサを削除できることを保証する
* @param decidedUpdater 構築中の情報へ新しい決定済みのパーサを追加しなおせることを保証する
* @param initialUpdater 構築中の情報へ新しい初期値を設定しなおせることを保証する
* @param currentNotExist 構築中の情報に現在設定中のパーサが存在しないことを保証する
* @param hierarchySelector 構築中の情報がパーサ階層を持つことを保証する
* @param hierarchyIsEmpty 構築中の情報が保持するパーサ階層が空の状態であることを保証する
* @tparam ConvertingField フィールドへ変換する型
* @tparam ConvertedField フィールドへ変換した型
* @tparam Input パーサの現在値の型
* @tparam UpdatingInitial 初期値の追加対象となる型
* @tparam ExistInitial 現在の初期値の型
* @tparam RemovedInitial 構築中の情報から設定済みの初期値を削除した後の型
* @tparam ExistDecided 現在の決定済みパーサの型
* @tparam RemovedDecided 構築中の情報から決定済みパーサを削除した後の型
* @tparam MergedInitial 現在の初期値と追加する初期値をマージした型
* @tparam ExistHierarchy 現在のパーサ階層の型
* @tparam UpdatedDecided 構築中の情報へ新しい決定済みパーサを追加しなおした型
* @tparam UpdatedInitial 構築中の情報へ新しい初期値を設定しなおした型
* @tparam UpdatedCategory 構築中の情報をラップする型
* @return 構築中の情報へ初期値を追加する型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
implicit final def UpdateInitial[
ConvertingField,
ConvertedField <: HList,
Input,
UpdatingInitial <: HList,
ExistInitial <: HList,
RemovedInitial <: HList,
ExistDecided,
RemovedDecided <: HList,
MergedInitial <: HList,
ExistHierarchy <: HList,
UpdatedDecided <: HList,
UpdatedInitial <: HList,
UpdatedCategory[_]
](
implicit
runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
applicative: Applicative[UpdatedCategory],
initialField: Field.Aux[
ConvertingField,
ConvertedField
],
initialSelector: Selector.Aux[
UpdatingInitial,
InitialRecord.T,
ExistInitial
],
initialRemover: Remover.Aux[
UpdatingInitial,
InitialRecord.T,
(ExistInitial, RemovedInitial)
],
initialMerger: Merger.Aux[
ExistInitial,
ConvertedField,
MergedInitial
],
decidedRemover: Remover.Aux[
RemovedInitial,
ParserDecided.T,
(ExistDecided, RemovedDecided)
],
decidedUpdater: Updater.Aux[
RemovedDecided,
FieldType[
ParserDecided.T,
List[Queue[OParser[_, MergedInitial]]]
],
UpdatedDecided
],
initialUpdater: Updater.Aux[
UpdatedDecided,
FieldType[
InitialRecord.T,
MergedInitial
],
UpdatedInitial
],
currentNotExist: Refute[
Selector[
UpdatingInitial,
ParserCurrent.T
]
],
hierarchySelector: Selector.Aux[
UpdatingInitial,
ParserHierarchy.T,
ExistHierarchy
],
hierarchyIsEmpty: ExistHierarchy === HNil
): Initial.Aux[
UpdatingInitial @@ (Input @@ ExistInitial),
ConvertingField,
UpdatedCategory[UpdatedInitial @@ (Input @@ MergedInitial)]
] = InitialInstances0.UpdateInitial
/**
* ラップされた型に対して初期値設定を行います。
*
* @param runCategory 初期値を持つ値を格納する型を決定するマーカー
* @param bind 平坦化変換が可能なことを保証する
* @param base ラップされた型に対して初期値設定が行えることを保証する
* @tparam ConvertingField フィールドへ変換する値
* @tparam ConvertedField フィールドへ変換した値
* @tparam DerivedInitial 初期値設定前の型
* @tparam OutputInitial 初期値設定後の型
* @tparam OutputCategory 構築中の情報をラップする型
* @return ラップされた型に対して初期値設定を行う型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
implicit final def CategoryInitial[
ConvertingField,
ConvertedField <: HList,
DerivedInitial,
OutputInitial,
OutputCategory[_]
](
implicit
runCategory: ResultCategory[OutputCategory] @@ Run.type,
bind: Bind[OutputCategory],
base: Initial.Aux[
DerivedInitial,
ConvertingField,
OutputCategory[OutputInitial]
]
): Initial.Aux[
OutputCategory[DerivedInitial],
ConvertingField,
OutputCategory[OutputInitial]
] = InitialInstances0.CategoryInitial
}
/**
* 初期値を持つフィールドを追加するための型クラスインスタンスの第1候補を内部的に定義します。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private object InitialInstances0 extends AnyRef {
/**
* 構築中の情報へ初期値を付与します(内部)。
*
* @param runCategory 動作設定を持つ値を格納する型を決定するマーカー
* @param applicative 構築中の情報をラップ可能なことを保証する
* @param initialField 初期値として付与する型がフィールドへ変換可能なことを保証する
* @param decidedUpdater 構築中の情報の決定済みパーサを更新できることを保証する
* @param initialUpdater 構築中の情報へ初期値を付与できることを保証する
* @param currentNotExist 構築中の情報が現在設定中のパーサを持たないことを保証する
* @param initialNotExist 構築中の情報がまだ初期値を持たないことを保証する
* @tparam ConvertingField フィールドへ変換する型
* @tparam ConvertedField フィールドへ変換した型
* @tparam UnusedKeys パーサへのオプション追加時に使用する幽霊型(動作設定時は未使用)
* @tparam InsertingInitial 初期値の付与対象となる型
* @tparam InsertedDecided 決定済みパーサを更新した後の型
* @tparam InsertedInitial 初期値を付与した後の型
* @tparam InsertedCategory 構築中の情報をラップする型
* @return 構築中の情報へ初期値を付与する型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private final def InsertInitial[
ConvertingField,
ConvertedField <: HList,
UnusedKeys,
InsertingInitial <: HList,
InsertedDecided <: HList,
InsertedInitial <: HList,
InsertedCategory[_]
](
implicit
runCategory: ResultCategory[InsertedCategory] @@ Run.type,
applicative: Applicative[InsertedCategory],
initialField: Field.Aux[
ConvertingField,
ConvertedField
],
decidedUpdater: Updater.Aux[
InsertingInitial,
FieldType[
ParserDecided.T,
List[Queue[OParser[_, ConvertedField]]]
],
InsertedDecided
],
initialUpdater: Updater.Aux[
InsertedDecided,
FieldType[
InitialRecord.T,
ConvertedField
],
InsertedInitial
],
currentNotExist: Refute[
Selector[
InsertingInitial,
ParserCurrent.T
]
],
initialNotExist: Refute[
Selector[
InsertingInitial,
InitialRecord.T
]
]
): Initial.Aux[
InsertingInitial @@ UnusedKeys,
ConvertingField,
InsertedCategory[InsertedInitial @@ (Unit @@ ConvertedField)]
] = new Initial[InsertingInitial @@ UnusedKeys] {
/**
* 最初の初期値として設定可能なフィールドです。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Member = ConvertingField
/**
* 最初の初期値の追加後に返すべき型です。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Result = InsertedCategory[InsertedInitial @@ (Unit @@ ConvertedField)]
/**
* 初期値を付与した結果を返します。
*
* @param derived まだ初期値を持たない値
* @param member 付与する初期値
* @return 構築中の情報へ初期値を付与した結果
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override def apply
(
derived: => InsertingInitial @@ UnusedKeys,
member: => super.Member
): super.Result = this (derived) = member.field
/**
* 構築中の情報へ初期値を付与します。
*
* @param derived まだ初期値を持たない値
* @param field 付与する初期値
* @return 構築中の情報へ初期値を付与した結果
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private[this] def update
(
derived: InsertingInitial @@ UnusedKeys,
field: ConvertedField
): super.Result = {
// 空の決定済みパーサを生成して追加
val defaultParserDecided: List[Queue[OParser[_, ConvertedField]]] = Queue.empty :: Nil
val insertedDecided: InsertedDecided = derived.unwrap.updated(ParserDecided, defaultParserDecided)
// 初期値を付与
val insertedInitial: InsertedInitial = insertedDecided.updated(InitialRecord, field)
// 再度タグ付けして返す
val result: InsertedInitial @@ (Unit @@ ConvertedField) = insertedInitial.wrap
result.pure
}
}
/**
* 構築中の情報へ初期値を追加します(内部)。
*
* @param runCategory 動作設定を持つ値を格納する型を決定するマーカー
* @param applicative 構築中の情報をラップ可能なことを保証する
* @param initialField 初期値として付与する型がフィールドへ変換可能なことを保証する
* @param initialSelector 構築中の情報から設定済みの初期値を取得できることを保証する
* @param initialRemover 構築中の情報から設定済みの初期値を削除できることを保証する
* @param initialMerger 設定済みの初期値と新しい初期値がマージ可能なことを保証する
* @param decidedRemover 構築中の情報から決定済みのパーサを削除できることを保証する
* @param decidedUpdater 構築中の情報へ新しい決定済みのパーサを追加しなおせることを保証する
* @param initialUpdater 構築中の情報へ新しい初期値を設定しなおせることを保証する
* @param currentNotExist 構築中の情報に現在設定中のパーサが存在しないことを保証する
* @param hierarchySelector 構築中の情報がパーサ階層を持つことを保証する
* @param hierarchyIsEmpty 構築中の情報が保持するパーサ階層が空の状態であることを保証する
* @tparam ConvertingField フィールドへ変換する型
* @tparam ConvertedField フィールドへ変換した型
* @tparam Input パーサの現在値の型
* @tparam UpdatingInitial 初期値の追加対象となる型
* @tparam ExistInitial 現在の初期値の型
* @tparam RemovedInitial 構築中の情報から設定済みの初期値を削除した後の型
* @tparam ExistDecided 現在の決定済みパーサの型
* @tparam RemovedDecided 構築中の情報から決定済みパーサを削除した後の型
* @tparam MergedInitial 現在の初期値と追加する初期値をマージした型
* @tparam ExistHierarchy 現在のパーサ階層の型
* @tparam UpdatedDecided 構築中の情報へ新しい決定済みパーサを追加しなおした型
* @tparam UpdatedInitial 構築中の情報へ新しい初期値を設定しなおした型
* @tparam UpdatedCategory 構築中の情報をラップする型
* @return 構築中の情報へ初期値を追加する型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private final def UpdateInitial[
ConvertingField,
ConvertedField <: HList,
Input,
UpdatingInitial <: HList,
ExistInitial <: HList,
RemovedInitial <: HList,
ExistDecided,
RemovedDecided <: HList,
MergedInitial <: HList,
ExistHierarchy <: HList,
UpdatedDecided <: HList,
UpdatedInitial <: HList,
UpdatedCategory[_]
](
implicit
runCategory: ResultCategory[UpdatedCategory] @@ Run.type,
applicative: Applicative[UpdatedCategory],
initialField: Field.Aux[
ConvertingField,
ConvertedField
],
initialSelector: Selector.Aux[
UpdatingInitial,
InitialRecord.T,
ExistInitial
],
initialRemover: Remover.Aux[
UpdatingInitial,
InitialRecord.T,
(ExistInitial, RemovedInitial)
],
initialMerger: Merger.Aux[
ExistInitial,
ConvertedField,
MergedInitial
],
decidedRemover: Remover.Aux[
RemovedInitial,
ParserDecided.T,
(ExistDecided, RemovedDecided)
],
decidedUpdater: Updater.Aux[
RemovedDecided,
FieldType[
ParserDecided.T,
List[Queue[OParser[_, MergedInitial]]]
],
UpdatedDecided
],
initialUpdater: Updater.Aux[
UpdatedDecided,
FieldType[
InitialRecord.T,
MergedInitial
],
UpdatedInitial
],
currentNotExist: Refute[
Selector[
UpdatingInitial,
ParserCurrent.T
]
],
hierarchySelector: Selector.Aux[
UpdatingInitial,
ParserHierarchy.T,
ExistHierarchy
],
hierarchyIsEmpty: ExistHierarchy === HNil
): Initial.Aux[
UpdatingInitial @@ (Input @@ ExistInitial),
ConvertingField,
UpdatedCategory[UpdatedInitial @@ (Input @@ MergedInitial)]
] = new Initial[UpdatingInitial @@ (Input @@ ExistInitial)] {
/**
* 初期値として設定可能なフィールドです。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Member = ConvertingField
/**
* 初期値の追加後に返すべき型です。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Result = UpdatedCategory[UpdatedInitial @@ (Input @@ MergedInitial)]
/**
* 構築中の情報が持つ初期値へ追加した結果を返します。
*
* @param derived 初期値を持つ値
* @param member 追加する初期値
* @return 構築中の情報が持つ初期値へ追加した結果
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override def apply
(
derived: => UpdatingInitial @@ (Input @@ ExistInitial),
member: => super.Member
): super.Result = this (derived) = _.merge(member.field)
/**
* 構築中の情報が持つ初期値へ追加した結果を返します。
*
* @param derived 初期値を持つ値
* @param function 初期値を追加する処理
* @return 構築中の情報が持つ初期値へ追加した結果
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private[this] def update
(
derived: UpdatingInitial @@ (Input @@ ExistInitial),
function: ExistInitial => MergedInitial
): super.Result = {
// 構築した情報からタグを外す
val updatingInitial: UpdatingInitial = derived.unwrap
// 設定済みの初期値を取得し、削除する
val (existInitial, removedInitial):
(ExistInitial, RemovedInitial) =
updatingInitial.remove(InitialRecord)
// 初期値が変わるため、決定済みパーサを全て破棄する
val removedDecided: RemovedDecided = removedInitial - ParserDecided
// 新しい初期値に対応する空の決定済みパーサを設定しなおす
val defaultParserDecided: List[Queue[OParser[_, MergedInitial]]] = Queue.empty :: Nil
val decidedInitial: UpdatedDecided =
removedDecided.updated(ParserDecided, defaultParserDecided)
// 新しい初期値で更新する
val updatedInitial: UpdatedInitial =
decidedInitial.updated(InitialRecord, function(existInitial))
// 再度タグ付けして返す
val result: UpdatedInitial @@ (Input @@ MergedInitial) = updatedInitial.wrap
result.pure
}
}
/**
* ラップされた型に対して初期値設定を行います(内部)。
*
* @param runCategory 初期値を持つ値を格納する型を決定するマーカー
* @param bind 平坦化変換が可能なことを保証する
* @param base ラップされた型に対して初期値設定が行えることを保証する
* @tparam ConvertingField フィールドへ変換する値
* @tparam ConvertedField フィールドへ変換した値
* @tparam DerivedInitial 初期値設定前の型
* @tparam OutputInitial 初期値設定後の型
* @tparam OutputCategory 構築中の情報をラップする型
* @return ラップされた型に対して初期値設定を行う型クラスインスタンス
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
private final def CategoryInitial[
ConvertingField,
ConvertedField <: HList,
DerivedInitial,
OutputInitial,
OutputCategory[_]
](
implicit
runCategory: ResultCategory[OutputCategory] @@ Run.type,
bind: Bind[OutputCategory],
base: Initial.Aux[
DerivedInitial,
ConvertingField,
OutputCategory[OutputInitial]
]
): Initial.Aux[
OutputCategory[DerivedInitial],
ConvertingField,
OutputCategory[OutputInitial]
] = new Initial[OutputCategory[DerivedInitial]] {
/**
* 初期値として設定可能なフィールドです。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Member = ConvertingField
/**
* 初期値の追加後に返すべき型です。
*
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override type Result = OutputCategory[OutputInitial]
/**
* ラップされた型に対して初期値を追加した結果を返します。
*
* @param derived 初期値を持つ値
* @param member 追加する初期値
* @return 初期値を追加した結果
* @author Kynthus Auoeau
* @since 1.0.0
* @version 1.0.0
*/
override def apply
(
derived: => OutputCategory[DerivedInitial],
member: => super.Member
): super.Result = derived >>= (_.initial(member))
}
}