2015-09-21 5 views
6

Lets sagen, ich habe die folgendetypeclass für (was zu sein scheint) eine kontra Funktors Implementierung Funktion Inversion

import Control.Category (Category, (.), id) 

data Invertible a b = Invertible (a -> b) (b -> a) 

instance Category Invertible where 
    id = Invertible Prelude.id Prelude.id 
    (Invertible f f') . (Invertible g g') = 
    Invertible (f Prelude.. g) (g' Prelude.. f') 

invert (Invertible x y) = Invertible y x 

Beachten Sie, dass die folgenden Bedingungen erfüllt ist:

invert (g . f) == invert f . invert g 

Diese Struktur sehr ähnlich scheint ein contravariant functor (wikipedia), da sie die gleiche Axiom folgt:

F(g . f) = F(f) . F(g) 

In meinem Fall F ist einfach invert.

ich Data.Functor.Contravariant.contramap sah, die eine Funktion des Typs hat:

(a -> b) -> f b -> f a 

Aber ich wusste nicht, wie würde ich das in meiner Situation umsetzen würde. Zum Beispiel kann ich keine vernünftige Wahl für f erarbeiten, und in meiner Situation gibt es keine Funktion a -> b, nur invert.

Jedoch passt invert nichtsdestoweniger das mathematische Axiom eines kontravarianten Funktors, also denke ich, dass ich das in eine existierende Klasse einbauen kann, aber ich kann einfach nicht herausfinden, welches und wie ich es mache. Jede Hilfe oder Hinweise würden geschätzt werden.

+1

Sie könnten diesen Blogbeitrag interessant finden: http://gelisam.blogspot.com/2013/07/the-commutative-monad.html –

+2

Das Problem, meiner bescheidenen Meinung nach, ist, dass "invert" ein kontravarianter Endofunkortist in der Kategorie "Invertible", während "Contravariant f" ein kontravariantes Endofunctor in der Kategorie "Hask" ist. –

+0

@AaditMShah, das war meine Vermutung, aber ich kenne nicht genug Kategorientheorie, um zuversichtlich zu sein. – dfeuer

Antwort

8

Eine Kategorie hat zwei Sammlungen: Objekte und Morphismen.

Der üblicher Haskell Auftakt, und es scheint, dass die Klassen in Data.Functor.Contravariant, nur auf einen sehr engen Bereich arbeiten, dass die Kategorie ist, wo Typen Objekte und Funktionen sind morphisms sind, bezeichnet in der Regel Hask. Die Standard Functor Klasse ist auch sehr eng: Sie repräsentieren nur Endofunkter auf Hask: Sie müssen Typen zu Typen und Funktionen zu Funktionen nehmen.

Nehmen Sie zum Beispiel den Funktor Maybe. Die Art, wie Maybe auf Typen wirkt, ist nur, dass es Typen a zu Maybe a nimmt. Maybe Karten Int zu Maybe Int und so weiter (ich weiß, das klingt ein bisschen trivial). Was es morphisms tut codiert wird durch fmap: fmap nimmt f :: (a -> b), ein Morphismus zwischen zwei Objekten in Hask, und ordnet sie fmap f :: (Maybe a -> Maybe b), eine andere morphism in Hask zwischen den Objekten, die die Funktors Karten. In Haskell konnten wir keine Functor definieren, die z.B. Int zu Char - alle Haskell Functor s müssen Typ Konstruktoren sein - aber in der allgemeinen Kategorientheorie könnten wir.

Control.Category verallgemeinert ein wenig: die Objekte einer Control.Category Kategorie C noch Typen sind [1] wie in Hask, aber seine morphisms sind Dinge vom Typ C a b. In Ihrem Beispiel sind die Objekte also immer noch beliebige Typen, aber Ihre Morphismen sind Dinge vom Typ Invertible a b. Da Ihre Morphismen keine Funktionen sind, können Sie die Standardklassen Functor nicht verwenden.

aber es ist eine nette Übung in Ihre Kategorie Theorie Know-how aufzubauen, um eine Funktor Klasse zu definieren, die eher zwischen Category Kategorien arbeiten als unter der Annahme Hask, die Ihr Beispiel erfassen würde. Denken Sie daran, ein Funktor wirkt auf Objekte (Typen) und Morphismen.

Ich werde Sie damit verlassen - fühlen Sie sich frei zu kommentieren, wenn Sie mehr Führung wünschen.


[1] Das Ignorieren PolyKinds, das dies etwas allgemeinere macht.

+0

Du hast mich dazu geschlagen. Ich wusste, dass das Problem darin lag, dass der OP versuchte, 'Prelude.id' mit' Control.Category.id' und 'Prelude..' mit' Control.Category..' zu verbinden, aber ich hatte nicht die Zeit dazu schreibe eine Antwort. Ich wurde vom folgenden Blog-Eintrag in die Irre geführt: http://gelisam.blogspot.com/2013/07/the-commutative-monad.html –

+2

Lets sagen, dass wir umkehren, was in Control.Categorical.fmap gefunden wird, das ist "rab -> t (fa) (fb) '. Anstatt umgekehrt zu sein: contramap :: r a b -> t (f b) (f a) '. Sei r = Invertierbar und t = Invertierbar. Von hier aus haben wir 'contramap :: Invertierbares a b -> Invertierbares (f b) (f a)'. Ich denke, an diesem Punkt brauchen wir nur "f" um Id zu sein? – Clinton

+0

@ Clinton In der Tat. Sie würden 'class (Kategorie c, Kategorie d) => Contravariant f c d | definieren f c -> d, f d -> c wobei contramap :: cxy -> d (fy) (fx) '. Dann würde man 'instance Contravariant Identity Invertible Invertible definieren, wobei contramap (Invertierbare f g) = Invertierbare (Identity. G. RunIdentity) (Identität. F. RunIdentity)'. Jetzt haben Sie 'contramap' isomorph zu' invert'. Allerdings bezweifle ich, dass Sie 'contramap' verwenden möchten, weil Sie mit einem unnötigen Identity-Wrapper umgehen müssten. Sie sind besser dran, indem Sie einfach direkt die Funktion 'Invertieren' verwenden. –

Verwandte Themen