Extiendo una respuesta a Haskell setting record field based on field name string? para agregar un getField
genérico. Estoy usando gmapQi
, y quiero generar un error si el tipo del subelemento encontrado no coincide con el tipo esperado. Quiero que el mensaje de error incluya el nombre del tipo que se encontró, así como el nombre del tipo esperado. La función tiene el siguiente aspecto:typeOf on return type
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics
import Prelude hiding (catch)
import Control.Exception
getField :: (Data r, Typeable v) => Int -> r -> v
getField i r = gmapQi i (e `extQ` id) r
where
e x = error $ "Type mismatch: field " ++ (show i) ++
" :: " ++ (show . typeOf $ x) ++
", not " ++ (show . typeOf $ "???")
---------------------------------------------------------------------------------
data Foo = Foo Int String
deriving(Data, Typeable)
handleErr (ErrorCall msg) = putStrLn $ "Error -- " ++ msg
main = do
let r = Foo 10 "Hello"
catch (print (getField 0 r :: Int)) handleErr
catch (print (getField 0 r :: String)) handleErr
catch (print (getField 1 r :: Int)) handleErr
catch (print (getField 1 r :: String)) handleErr
El problema es que no sé qué poner en su lugar de "???"
para obtener el tipo de retorno de la función getField
(es decir, la manera de cosificar v
de la firma de tipo).
brillante! Gracias – pat