2012-11-02 4 views
5

Dies ist eine Haskell newb Frage wahrscheinlich mit der IO() Monade zu tun.Happstack eine Lesedatei anzeigen

Ich habe eine Funktion in einem Happstack.Server Programm, das eine Antwort für einen Dateiupload generiert.

postFile = do methodM POST 
       decodeBody filePolicy 
       (tmp, name, meta) <- lookFile "upload" 
       ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta] 

Das funktioniert gut. Jetzt möchte ich, dass der Inhalt der hochgeladenen Datei sowie der lokale Tempname, der ursprüngliche Name und die Metadaten des Inhaltstyps angezeigt werden. Ich war die Annahme, dass, da dies alles stattfindet, in einem do Block ist, konnte ich nur

postFile = do methodM POST 
       decodeBody filePolicy 
       (tmp, name, meta) <- lookFile "upload" 
       contents <- readFile tmp 
       ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta, "\n\n", contents] 

aber das reicht mir eine Reihe von Fehlern, die mir zu sagen, scheint etwas im Busch ist mit dem decodeBody Anruf.

... 
/home/inaimathi/projects/happstack-tutorial/parameters.hs:23:15: 
    No instance for (Happstack.Server.Internal.Monads.WebMonad 
         Response IO) 
     arising from a use of `decodeBody' 
    Possible fix: 
     add an instance declaration for 
     (Happstack.Server.Internal.Monads.WebMonad Response IO) 
    In a stmt of a 'do' block: decodeBody filePolicy 
    In the expression: 
     do { methodM POST; 
      decodeBody filePolicy; 
      (tmp, name, meta) <- lookFile "upload"; 
      contents <- readFile tmp; 
      .... } 
    In an equation for `postFile': 
     postFile 
      = do { methodM POST; 
       decodeBody filePolicy; 
       (tmp, name, meta) <- lookFile "upload"; 
       .... } 
... 

Ich bin mir nicht sicher, was hier falsch läuft. Kann mir jemand etwas beibringen?


EDIT3:

Das wird lernen, mich zu voreiligen Schlüsse ziehen.

Die zusätzlichen Fehler, die ich bekam, waren alle auf falsch installierte Bibliotheken zurückzuführen. Löschen Sie meine ~/.ghc, dann installieren Sie happstack wieder behoben.

+2

Ich kenne Happstack nicht, aber Sie müssen wahrscheinlich 'liftIO $ readFile tmp' verwenden. ' – hammar

+1

Wie andere schon gesagt haben, brauchen Sie nur' liftIO '. Ich werde dem Crashkurs einen Abschnitt hinzufügen. – stepcut

Antwort

11
No instance for (Happstack.Server.Internal.Monads.WebMonad 
         Response IO) 

Übersetzung: Ihr do -Block ist nicht die IO Monade aber einige andere Monade. Glücklicherweise stellt sich heraus, eine Instanz von MonadIO sein:

class Monad m => MonadIO m where 
    liftIO :: IO a -> m a 

Wie Sie sehen, eine solche Instanz einfach bietet eine Möglichkeit, ‚Aufzug‘ IO Aktionen vom IO-Monade in sich, so in Ihrem Fall brauchen Sie nur :

contents <- liftIO $ readFile tmp 

die Implementierung von liftIO hängt natürlich von m, aber in einem typischen Monade Transformator stapelt es verwendet lift und liftIO an die IO-Monade nach innen zu erhalten; siehe z.B. die implementations for the other monad transformers in the Transformers library.

+0

Der Frage wurde nach dem Ausprobieren dieses Vorschlags ein Bearbeitungsschritt hinzugefügt. es scheint, es ist nicht ganz so einfach wie 'liftIO' hinzuzufügen. – Inaimathi

+0

Was ist der Typ von postFile? – Fixnum

+0

'Happstack.Server.Internal.Monads.ServerPartT IO String' (': t' in 'ghci' meldet' Happstack.Server.Internal.Monads.ServerPartT IO [Char] ') – Inaimathi