In this answer, Gabriel Gonzalez mostra come mostrare che id
è l'unico abitante di forall a. a -> a
. Per fare ciò (nella più formale iterazione della dimostrazione), mostra che il tipo è isomorfo su ()
usando lo Yoneda lemma, e dal momento che ()
ha solo un valore in esso, quindi deve essere il tipo di id
. Riassunto, la sua prova è in questo modo:Come faccio a dimostrare che un tipo Haskell è abitato da una sola funzione?
Yoneda dice:
Functor f => (forall b . (a -> b) -> f b) ~ f a
Se
a =()
ef = Identity
, questo diventa:(forall b. (() -> b) -> b) ~()
E poiché banalmente
() -> b ~ b
, il LHS è fondamentalmente il tipo diid
.
Questo sembra un po 'un "trucco magico" che funziona bene per id
. Sto cercando di fare la stessa cosa per un tipo di funzione più complesso:
(b -> a) -> (a -> b -> c) -> b -> c
ma non ho idea da dove iniziare. So che è abitata da \f g x = g (f x) x
, e se ignori le cose brutte ⊥
/undefined
, sono abbastanza sicuro che non ci sono altre funzioni di questo tipo.
Non credo che il trucco di Gabriel sarà immediatamente applicare qui in qualsiasi modo scelgo i tipi. Ci sono altri approcci (che sono ugualmente formali!) Con cui posso mostrare l'isomorfismo tra questo tipo e ()
?
Ah, avevo pensato di usare il curry per ottenere '((a, b) -> c)', ma non di cambiare l'ordine degli argomenti, in qualche modo - questo ha fatto il trucco! – Lynn
Puoi anche usare 'f' come hom-functor covariante invece di' Id': '(a -> b -> c) -> b -> c' ~' ((a, b) -> c) -> (->) bc' ~ 'b -> (a, b)'. – user3237465
potresti per favore racchiudere la parentesi completa con "forall b a. (b -> a) -> b -> forall c. (a -> b -> c) -> c' type, affinché l'ambito di ciascun 'forall' sia visto esplicitamente? –