2015-01-14 12 views
12

Bir tür ailesini içeren bu veri türü için fmap yazmak mümkün mü?

data T a = T Integer (P (T a) a) 

bunların açısından tanımlanmış

type family P (x :: *) (a :: *) :: * where 
    P x() = x 
    P x a = (x, a) 

ve veri tipi (izomorfizm A x 1 ≅ bir yansıtmak için gerekiyordu) aşağıdaki tür ailesi göz önüne alındığında, buluşa göre sistemlerin bazı tip hackery bir yazmak için İkinci için Functor örneği?

instance Functor T where 
    fmap f = undefined -- ?? 

Sezgisel olarak f türüne bağlı olarak ne yapacağını açıktır, ama ben Haskell bunu ifade etmek nasıl bilmiyorum.

+2

Benim bağırsağım, parametrikliği ihlal etmesi gerektiğinden mümkün olmaması gerektiğini söylüyor. – Cactus

cevap

12

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.

İlgili konular