Haskell: getting the static type of an expression

前端 未结 2 1073
死守一世寂寞
死守一世寂寞 2020-12-25 08:23

I\'m looking for a function that does what the GHCi :type command does.

Ideally, it would have a signature something like

getStaticType :: a -> St         


        
相关标签:
2条回答
  • 2020-12-25 09:09

    try http://www.haskell.org/haskellwiki/GHC/As_a_library

    typed targetFile targetModule = do
     defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
      runGhc (Just libdir) $ do
    
       dflags <- getSessionDynFlags
       let dflags' = xopt_set dflags Opt_ImplicitPrelude
       setSessionDynFlags dflags'
    
       target <- guessTarget targetFile Nothing
       setTargets [target]
       load LoadAllTargets
    
       m <- getModSummary $ mkModuleName targetModule
       p <- parseModule m
       t <- typecheckModule p
    
       return $ typecheckedSource d
    
    0 讨论(0)
  • 2020-12-25 09:12

    You can do it like this:

    import Data.Typeable
    
    getStaticType :: Typeable a => a -> String
    getStaticType = show . typeOf
    

    Note that the type must be an instance of Typeable. You can derive Typeable automatically using the DeriveDataTypeable Haskell language extension and ... deriving (Typeable, ...).

    Also note that polymorphic types cannot be identified in this way; you must always call a function with a specific type, so you can never get that polymorphic type information that you get in GHCi with compiled Haskell code.

    The way GHCi does it is that it uses the GHC API to analyse an intermediary Haskell abstract syntax tree (AST) that contains type information. GHCi does not have the same restricted environment that your typical compiled Haskell program does; it can do lots of stuff to find out more information about its environment.

    With TemplateHaskell, you can do it like this; first, create this module:

    module TypeOf where
    
    import Control.Monad
    
    import Language.Haskell.TH
    import Language.Haskell.TH.Syntax
    
    getStaticType :: Name -> Q Exp
    getStaticType = lift <=< fmap pprint . reify
    

    Then, in a different module (very important), you can do the following:

    {-# LANGUAGE TemplateHaskell #-}
    
    import TypeOf
    
    main = putStrLn $(getStaticType 'zipWith)
    

    This program outputs:

    GHC.List.zipWith :: forall a_0 b_1 c_2 . (a_0 -> b_1 -> c_2) ->
                                             [a_0] -> [b_1] -> [c_2]
    

    You can use a better pretty-printer than the pprint function; take a look at the Language.Haskell.TH.Ppr module.

    0 讨论(0)
提交回复
热议问题