Agda で代数構造の新しいレコード型を宣言する 2 つのスタイルを比較したいと思います。
標準の Agda パッケージで使用されているスタイルに従って、次のようにAlgebra定義できます。BoundedJoinSemilattice
record IsBoundedJoinSemilattice {a ℓ} {A : Set a}
(_≈_ : Rel A ℓ) (_∨_ : Op₂ A) (⊥ : A) : Set (a Level.⊔ ℓ) where
field
isCommutativeMonoid : IsCommutativeMonoid _≈_ _∨_ ⊥
idem : Idempotent _≈_ _∨_
open IsCommutativeMonoid isCommutativeMonoid public
record BoundedJoinSemilattice c ℓ : Set (suc (c ⊔ ℓ)) where
infixr 6 _∨_
infix 4 _≈_
field
Carrier : Set c
_≈_ : Rel Carrier ℓ
_∨_ : Op₂ Carrier
⊥ : Carrier
isBoundedJoinSemilattice : IsBoundedJoinSemilattice _≈_ _∨_ ⊥
open IsBoundedJoinSemilattice isBoundedJoinSemilattice public
commutativeMonoid : CommutativeMonoid _ _
commutativeMonoid = record {
Carrier = Carrier;
_≈_ = _≈_;
_∙_ = _∨_;
ε = ⊥;
isCommutativeMonoid = isCommutativeMonoid
}
このアプローチでは、 のフィールドは(名前の変更まで) 、、、およびなどの他のより抽象的な構造のフィールドBoundedJoinSemiLatticeと重複します。a をその「スーパータイプ」の 1 つとして表示するには、そのフィールドをスーパータイプのフィールドにマッピングする射影関数 (上記の関数など) を呼び出す必要があります。SetoidSemigroupMonoidCommutativeMonoidBoundedJoinSemiLatticeBoundedJoinSemiLatticecommutativeMonoid
ただし、このフィールドの重複は、あまり具体的でない代数構造からより具体的な代数構造を構築するコードの重要なボイラープレートにつながる可能性があります。より自然な定義は次のようになります (名前CommutativeMonoidを に変更CM):
record IsBoundedJoinSemilattice {c ℓ} (cm : CM c ℓ)
(⊥ : CM.Carrier cm) : Set (c Level.⊔ ℓ) where
field
isCommutativeMonoid : IsCM (CM._≈_ cm) (CM._∙_ cm) ⊥
idem : Idempotent (CM._≈_ cm) (CM._∙_ cm)
open IsCommutativeMonoid isCommutativeMonoid public
record BoundedJoinSemilattice c ℓ : Set (suc (c ⊔ ℓ)) where
field
commutativeMonoid : CM c ℓ
isBoundedJoinSemilattice : IsBoundedJoinSemilattice commutativeMonoid (CM.ε commutativeMonoid)
open CommutativeMonoid commutativeMonoid public using (Carrier; _≈_) renaming (
_∙_ to _∨_;
ε to ⊥
)
open IsBoundedJoinSemilattice isBoundedJoinSemilattice public
ここでの考え方は、CommutativeMonoidintoのフィールドを複製するのBoundedJoinSemilatticeではなく、後者が type の単一のフィールドを宣言することCommutativeMonoidです。次に、 を使用して、open...publicそのサブフィールドを含むレコードに「継承」します。実際、これは の標準ライブラリの他の場所で使用されているイディオムとまったく同じですが、Algebra.Structuresここでは継承されたフィールドの名前も変更して、継承コンテキストで適切に名前が付けられるようにしています。
この 2 番目の方法は冗長性が低いだけでなく、 aBoundedJoinSemilatticeから aを作成したいクライアント コードは、作成CommutativeMonoid中のレコードに単純にそれを引数として渡すことができます。一方、BoundedJoinSemilatticeゼロから を構築したいクライアント コードは、中間の を構築する必要がありますCommutativeMonoid。
Algebraモジュールがこの継承スタイルを使用しない 理由はありAlgebra.Structuresますか? たぶん、私が見つけていない 2 番目のアプローチに問題があるか、またはおそらく大きな違いはないでしょうBoundedJoinSemiLattice。CommutativeMonoid、2番目のアプローチの利便性の多くを回復します。