Sto estendendo una risposta a Haskell setting record field based on field name string? per aggiungere un generico getField
. Sto usando gmapQi
e voglio generare un errore se il tipo del sottoelemento incontrato non corrisponde al tipo atteso. Voglio che il messaggio di errore includa il nome del tipo incontrato e il nome del tipo previsto. La funzione è simile al seguente:typeOf sul tipo di ritorno
{-# 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
Il problema è, non so cosa mettere al posto di "???"
per ottenere il tipo di ritorno della funzione getField
(vale a dire come reificare v
dalla firma di tipo).
brillante! Grazie – pat