2014-06-06 10 views
14

Ho bisogno della seguente classe di funzioni:Il concetto di un "omomorfismo interleaved" è una cosa reale?

class InterleavedHomomorphic x where 
    interleaveHomomorphism :: (forall a . f a -> g a) -> x f -> x g 

Ovviamente il nome che ho inventato, perché non è in alcun modo un termine ufficiale per qualsiasi cosa, e la classe tipo di cui sopra non è molto elegante. È un concetto che ha un nome o anche un'implementazione in qualche biblioteca? C'è un modo più ragionevole per farlo?


Lo scopo di questa funzione è che ho qualche contesto f che annota alcuni dati (Foo e Bar sono solo casuali strutture dati di esempio per il bene di questa domanda):

data Foo f = One (f (Bar f)) | Product (f (Foo f)) (f (Foo f)) 
data Bar f = Zero | Succ (f (Bar f)) 

I vorrebbe trasformare il contesto dei dati in modo polimorfico; conoscendo solo l'omomorfismo tra i contesti e non (necessariamente) preoccupandosi dei dati stessi. Questo sarebbe fatto fornendo instance InterleavedHomomorphic Foo e instance InterleavedHomomorphic Bar nell'esempio sopra.

risposta

17

Quindi, assumendo f e g sono funtori appropriati, forall a. f a -> g a è una trasformazione naturale. Potremmo fare un po 'più carina:

type f ~> g = forall a. f a -> g a 

trasformazioni naturali come questo Formiamo una categoria di Haskell Funtori, in modo da quello che hai è un funtore da quello a qualche altra categoria.

Seguendo i passaggi dei normali Haskell Functors, avrebbe forse senso avere x un endofunctor, mappando i Functional ad altri Functional. Questo è simile, ma non identico, a quello che hai:

class FFunctor x where 
    ffmap :: (f ~> g) -> (x f ~> x g) 

Tuttavia, nel tuo caso x f e x g non sono funtori, e x f -> x g è una funzione normale piuttosto che una trasformazione naturale. Tuttavia, il modello è abbastanza vicino da essere intrigante.

Con questo in mente, sembra che x sia ancora un esempio di un funtore, solo tra due diverse categorie. Passa dalla categoria di Functional alla categoria di x s con diverse strutture. Ogni possibile x, come Foo, forma una categoria con oggetti come Foo [] e Foo Maybe e trasformazioni tra di loro (Foo [] -> Foo Maybe). La tua funzione interleaveHomomorphism "solleva" trasformazioni naturali in questi x-morphisms, proprio come fmap "solleva" le normali funzioni (a -> b) in funzioni nell'immagine del funtore (f a -> f b).

Quindi sì: il tuo typeclass è un funtore come lo Functor, tranne tra due diverse categorie. Non so di un nome specifico per questo, in gran parte perché non so un nome specifico per costrutti come x.

non Più in generale, sono nemmeno sicuro un nome specifico avrebbe senso. A questo punto, ci sarebbe probabilmente un bel typeclass funtore generico che andiamo tra eventuali due categorie.Forse qualcosa del tipo:

class (Category catA, Category catB) => GFunctor f catA catB where 
    gfmap :: catA a b -> catB (f a) (f b) 

Questo probabilmente esiste già in una libreria da qualche parte.

Sfortunatamente, questo particolare approccio alla definizione di diversi funtori richiederebbe un po 'di rumore extra newtype dal momento che (->) è già una categoria. In effetti, ottenere tutti i tipi di allineare correttamente sarà un po 'un dolore.

Quindi è probabilmente più semplice chiamarlo semplicemente XFunctor o qualcosa del genere. Inoltre, immagina lo pun potential!

EDIT: Sembra categories fornisce un tipo CFunctor come questo, ma un po 'più intelligente:

class (Category r, Category s) => CFunctor f r s | f r -> s, f s -> r where 
    cmap :: r a b -> s (f a) (f b) 

Tuttavia, non sono sicuro che anche questo è abbastanza generale! Penso che potremmo volere che sia anche più polimorfico sui generi.

+3

Certo, qualcosa come "GFunctor" esiste; anzi i matematici considererebbero endofunzionisti come quelli che abbiamo in ** Hask ** un caso molto speciale e, in particolare, trattano i funtori tra diverse categorie. Parametri di Edward ['class (Category r, Category t) => Functor f r t | fr -> t, ft -> r'] (http://hackage.haskell.org/package/categories-1.0.6/docs/Control-Categorical-Functor.html) 'dove fmap :: rab -> t (fa) (fb) '. – leftaroundabout

+0

@leftaroundabout: Grazie! Ho trovato la vecchia versione in 'category-extras', ma sembra che' categories' sia il pacchetto più nuovo e migliore da usare. –

+0

Non vedo come 'f' e' g' debbano essere dei funtori. Tuttavia, ha senso trattare 'x' come un funtore da una categoria di morfismi generici quantificati in modo esistenziale in un'altra categoria. È bello vedere che "CFunctor" esiste, ma è un peccato che non abbia una struttura molto rigorosa e completa costruita attorno ad esso per essere utile. Credo che dovrò comunque specializzarmi per il mio caso d'uso. Ma questa risposta ha senso quindi lo accetterò! – dflemstr

0

Bar f somiglia allo Free MonadFree f().

Quindi Foo è un do con uno o due <-. Forse continuare da lì ...

+0

Come ho detto nella domanda, ho appena creato i tipi di dati 'Foo' e' Bar'. In realtà, mi occupo di strutture dati molto diverse. – dflemstr

0

Per quello che vale, è possibile riformulare una versione semplificata del vostro esempio come

data Bar' r = Zero | Succ r 
type Bar f = fix (Bar' . f) 

Per ogni coppia di trasformazioni naturali e eta1 :: f ~> geta2 :: Bar' ~> h otteniamo una trasformazione naturale (eta2 . eta1) :: (Bar' . f) ~> (h . g). E possiamo sollevare questa trasformazione naturale sul punto fisso nel modo più ovvio per ottenere fixed (eta2 . eta1) :: Bar f -> fix (h . g). Quindi, il tuo "omomorfismo interlacciato" è solo un caso speciale di questa costruzione per quando abbiamo eta2 = id.

Nel complesso si tratta di una costruzione piuttosto standard (soprattutto per i casi in cui f è una monade o una coma), anche se non sono sicuro che abbia un nome particolare ampiamente riconosciuto.

Problemi correlati