Dies ist Follow-up zu meinem vorherigen question über Typ-indexierte Karte. Nach der Diskussion in den Kommentaren poste ich hier das eigentliche Problem, um zu sehen, ob es eine saubere Möglichkeit gibt, dies zu lösen, indem man eine abhängige Programmierung verwendet.Weitergabe von Laufzeitinformationen für polymorphe Funktion
Das Problem ist, dass bestimmte Laufzeit Informationen, die wir für eine Typklassenfunktion benötigen - wir haben verschiedene Arten von Nachrichten über die Leitung kommen, und wir verwenden diese Funktion zu tun Nachricht spezifische Verarbeitung mit der Laufzeitkonfiguration - wie Übergeben wir Laufzeitinformationen (eine Laufzeitkonfiguration für jede Typinstanz) an diese Funktion?
Toy Code unten mit Kommentaren - wir typeclass Funktion f
innerhalb g
verwenden, die Laufzeitinformationen erhält und wendet sie auf f
- btw, der Satz von Nachrichtentypen a
ist fest - so können wir geschlossen typefamilies verwenden, wenn es sein muss:
module Main where
main :: IO()
main = do
let runtimeinfo = Mesg { aString = "someheader"}
builder = (\x -> Mesg { aString = (aString runtimeinfo) ++ (aString x)})
-- should call function "app" on this line which will call function "g"
return()
data Mesg = Mesg {aString :: String} deriving Show
class Process a where
f :: a -> a -- FYI, in actual app, output type is (StateT a IO Builder)
-- We can't define builder below at compile-time because it is created at run-time in main above
--builder :: a -> a
instance Process Mesg where
f inp = Mesg { aString = (reverse (aString inp))} -- contrived example - a placeholder for some processing on message
-- g is not directly reachable from main - main calls a function "app" which
-- calls g (after receiving "inp" of type "a" over the wire) - so, to pass
-- builder, we have to pass it along. builder is from runtime configuration -
-- in this example, it is created in main. If it were part of typeclass Process,
-- we won't need to pass it along
g :: Process a => (a -> a) -> a -> a
g builder inp = builder $ f inp -- we call processing function f here with runtime builder
-- Alternative approach pseudo code - map here is created in main, and passed to g via app
{--
g :: (Process a, Typeable a) => Map String Dynamic -> a -> Maybe a
g map inp = (retrieve corresponding builder from map using type-indexed string), apply here with f
--}
Meine Lösung so weit ist typ indiziert Karte in g
die builder
für den Typ a
nachschlägt.
Ich denke, die Art von 'g' ist seltsam .. Warum gibt es eine Zeichenfolge zurück? Warum nicht mit einer Funktion ':: (Prozess a, Typable a) => Map String Dynamisch -> Maybe (a -> a)' beginnen, die den String aus dem 'TypeRep' berechnet und die gewünschte Funktion zurückgibt (in Maybe von Kurs). – user2407038
@ user2407038, meine schlechte über kommentierte Version von 'g'. Sollte zurückgeben "Vielleicht ein". Fest. – Sal