2014-12-18 2 views
6

Angenommen, ich habe die folgende Funktion bekommt:Haskell: Gibt es eine Möglichkeit, den Rückgabetyp einer Funktion aus der Funktion abzuleiten?

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => String -> IO b 
parse msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg) 

Es einen String parst in was auch immer ich es will. Wenn der String fehlerhaft ist, wird eine Ausnahme ausgelöst, die die Nachricht anzeigt, die nicht analysiert werden konnte.

Ich benutze diese Funktion in einem Do-Block der IO-Monade wie

(a,b) <- parse msg :: IO (Int,Int) 

und an einem anderen Ort wie

s <- parse msg :: IO String 

Nun, wenn ich die Ausnahme ausführlichere Berichterstattung machen will welcher Typ konnte nicht gelesen werden

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => String -> IO b 
parse msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++ 
         show (typeOf something_that_has_type_b)) 

Wie bekomme ich etwas, das Typ b hat?

Eine mögliche Abhilfe wäre, dies zu tun

import Data.Typeable 
import Text.Read (reads) 

parse :: (Read b, Typeable b) => b -> String -> IO b 
parse dummy msg = case reads msg of 
     [(value,"")] -> return value 
     _ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++ 
         show (typeOf dummy)) 

und es wie

s <- parse "" msg :: IO String 

Aufruf Aber das sieht ziemlich albern.

Gibt es eine Möglichkeit, den Rückgabetyp einer Funktion aus der Funktion abzuleiten?

+0

Zusätzlich: Was ist, wenn * Werte * eines bestimmten Typs zurückgegeben werden sollen, wenn angefordert, und ein Fehler, wenn ein unbehandelter Rückgabetyp angefordert wird? – Evi1M4chine

Antwort

12

Sie benötigen keine Dummy-Variable, Sie können ScopedTypeVariables Erweiterung verwenden.

+6

Es scheint, dass heutzutage all die coolen Kids 'Proxy' anstelle von' undefined' für diese Art von Dingen verwenden. – dfeuer

+0

@dfeuer Ja, das ist richtig. Es ist eine Schande, 'undefined' zu verwenden, wenn' Proxy' jetzt in 'base' ist. –

+3

Ja, der moderne Weg ist 'show (typeRep (Proxy :: Proxy b))'. – augustss