Agda kullanarak bu tür yüksek kaliteli programlar hakkında akıl yürütüyorum.
Buradaki sorun açıklamada belirtildiği gibi, (Agda içinde Set
) *
üzerine desen maçı istediğiniz parametericity ihlal olmasıdır. Bu iyi değil, o yüzden yapamazsın. Şahit vermelisin. Yani ,
data Aux x a = AuxUnit x | AuxPair x a
type family P (x :: Aux * *) :: * where
P (AuxUnit x) = x
P (AuxPair x a) = (x, a)
Ama bu yüzden sorunlar T
ifade eden gerekecek yapıyor:
P : Aux → Set → Set
P auxunit b = b
P (auxpair a) b = a × b
Veya Haskell: Aşağıdaki Sen aux türünü kullanarak limitiation üstesinden gelebilir
P : Set → Set → Set
P Unit b = b
P a b = a × b
mümkün değildir parametresinde tekrar eşleşme olması gerektiğinden, doğru
Aux
yapıcısını seçmek için.
"Basit" çözüm, T a ~ Integer
zaman a ~()
ve doğrudan T a ~ (Integer, a)
bildirmektir:
module fmap where
record Unit : Set where
constructor tt
data ⊥ : Set where
data Nat : Set where
zero : Nat
suc : Nat → Nat
data _≡_ {ℓ} {a : Set ℓ} : a → a → Set ℓ where
refl : {x : a} → x ≡ x
¬_ : ∀ {ℓ} → Set ℓ → Set ℓ
¬ x = x → ⊥
-- GADTs
data T : Set → Set1 where
tunit : Nat → T Unit
tpair : (a : Set) → ¬ (a ≡ Unit) → a → T a
test : T Unit → Nat
test (tunit x) = x
test (tpair .Unit contra _) with contra refl
test (tpair .Unit contra x) |()
Sen Haskell için bu kodlamak için deneyebilirsiniz.
Örn. 'idiomatic' Haskell type inequality
ben :) bir egzersiz olarak
Hmm Haskell sürümünü bırakacağım ya da data T a = T Integer (P (T a) a)
kast etmedi:
T() ~ Integer × (P (T())())
~ Integer × (T())
~ Integer × Integer × ... -- infinite list of integers?
-- a /=()
T a ~ Integer × (P (T a) a)
~ Integer × (T a × a) ~ Integer × T a × a
~ Integer × Integer × ... × a × a
olanlar doğrudan yanı kodlamak daha kolaydır.
Benim bağırsağım, parametrikliği ihlal etmesi gerektiğinden mümkün olmaması gerektiğini söylüyor. – Cactus