2016-06-30 18 views
5

Sagen wir, ich habe einige typeclass:Kann ich ein Typklassenwörterbuch explizit an eine Funktion übergeben?

data Foo = Foo deriving (Show) 

class Monad m => MonadFoo m where 
    getFoo :: m Foo 

Seit GHC typeclasses über Wörterbuch vorbei (Verwendungen von SPECIALIZE ungeachtet) implementiert, es verwandelt sich effektiv getFoo in etwa wie folgt unter der Haube:

data MonadFooDict m = MonadFooDict { getFoo :: m Foo } 

... und fügt zu Beginn von Aufrufen an getFoo ein zusätzliches Argument ein, das das Wörterbuch umrahmt.

Manchmal möchte ich eine Instanz dynamisch auswählen, daher kann es auch wünschenswert sein, ein Wörterbuch selbst zu übergeben. Ich kann das selbst simulieren, indem ich eine Instanz erstelle, die das Wörterbuch für mich aufbereitet.

newtype DynamicMonadFoo a = DynamicMonadFoo 
    { runFoo :: MonadFooDict DynamicMonadFoo -> a } 
    deriving (Functor, Applicative, Monad 
      , MonadReader (MonadFooDict DynamicMonadFoo)) 

instance MonadFoo DynamicMonadFoo where 
    getFoo = join $ asks _getFoo 

, nun gegeben einige Funktion mit einem MonadFoo Einschränkung, kann ich die runFoo Funktion nutzen es eine explizite typeclass Wörterbuch weitergeben müssen:

showCurrentFoo :: MonadFoo m => m String 
showCurrentFoo = do 
    foo <- getFoo 
    return ("current foo: " ++ show foo) 

ghci> runFoo showCurrentFoo MonadFooDict { _getFoo = return Foo } 
"current foo: Foo" 

Das ist wirklich cool, aber es scheint wie eine solche einfache Aufgabe, dass GHC irgendeine Art von Bibliothek ausstellen könnte, um dies ohne all das zu tun (und idealerweise in einer Weise, die besser mit nicht-monadischen Typklassen funktionieren würde). Wenn man bedenkt, dass GHC einige "reflexionsähnliche" Fähigkeiten wie Data.Typeable hat, scheint dies nicht außerhalb der Möglichkeiten zu liegen, aber ich bin mir nicht sicher, ob es tatsächlich in irgendeiner Form existiert.

Erlauben eventuell vorhandene eingebaute oder andere Bibliotheken dies automatisch?

+0

Sie können mit der neuen expliziten Typ Anwendungserweiterung, mehr Details berechtigte [hier] (https://ghc.haskell.org/trac/ghc/wiki/ExplicitTypeApplication) – pdexter

+0

@pdexter Wenn ich etwas nicht vermisse, scheint das nichts mit mir zu tun - es scheint hauptsächlich syntaktisch zu sein und mit Werten am Typ zu arbeiten Ebene ausschließlich, während diese Frage ich s über die Übergabe eines dynamischen Laufzeitwerts als Typklassenwörterbuch. Allerdings könnte ich die Verbindung falsch interpretieren, in welchem ​​Fall eine Antwort, die das zeigt, sehr geschätzt würde! –

Antwort

5

es ein Artikel zu diesem Thema an der School of Haskell ist:

gegen Ende

Reflecting values to types and back

Siehe Abschnitt Dynamically constructing type-class instances und But what about manual dictionaries?

+6

Link-only-Antworten werden von StackOverflow abgeraten. Bitte fügen Sie den interessanten Inhalt hier ein. –

+0

Das ist sauber, aber letzten Endes scheint es nicht so, als würde es die Platten um so viel reduzieren ... tatsächlich scheint es das erheblich zu verkomplizieren. [Vergleichen Sie diese beiden Implementierungen] (https://gist.github.com/lexi-lambda/71ee8ea84127d8318a121c6acf49d331) für den Unterschied. Natürlich sieht es so aus, als ob dieser Ansatz viel besser für nicht-monadische Typklassen funktionieren kann, und das in dem Beitrag, den Sie verlinkt haben, erwähnte Performance-Bit ist interessant. Sonst scheint es nicht so, als würdest du hier viel gewinnen ... ist das genau? –

+2

Auch sollte ich wahrscheinlich erwähnen, dass ich gelesen habe, [Functional Pearl: Implicit Configurations] (http://okmij.org/ftp/Haskell/tr-15-04.pdf), das Papier, das das Reflexionspaket inspiriert, zu sein sehr zugänglich und hilfreich, um die Konzepte auf einer höheren Ebene als die Kernausgabe zu durchforsten. –