Ответ 1
Вы можете сделать это следующим образом:
import Data.Typeable
getStaticType :: Typeable a => a -> String
getStaticType = show . typeOf
Обратите внимание, что тип должен быть экземпляром Typeable
. Вы можете получить Typeable
автоматически, используя расширение языка DeriveDataTypeable
Haskell и ... deriving (Typeable, ...)
.
Также обратите внимание, что полиморфные типы не могут быть идентифицированы таким образом; вы всегда должны вызывать функцию с определенным типом, поэтому вы никогда не сможете получить информацию о полиморфном типе, которую вы получаете в GHCi с компилированным кодом Haskell.
Способ GHCi заключается в том, что он использует API GHC для анализа промежуточного дерева синтаксиса Haskell (AST), которое содержит информацию о типе. GHCi не имеет такой же ограниченной среды, что и ваша типичная скомпилированная программа Haskell; он может сделать много вещей, чтобы узнать больше информации о своей среде.
С TemplateHaskell вы можете сделать это так: сначала создайте этот модуль:
module TypeOf where
import Control.Monad
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
getStaticType :: Name -> Q Exp
getStaticType = lift <=< fmap pprint . reify
Затем в другом модуле (очень важно) вы можете сделать следующее:
{-# LANGUAGE TemplateHaskell #-}
import TypeOf
main = putStrLn $(getStaticType 'zipWith)
Эта программа выводит:
GHC.List.zipWith :: forall a_0 b_1 c_2 . (a_0 -> b_1 -> c_2) ->
[a_0] -> [b_1] -> [c_2]
Вы можете использовать лучший симпатичный принтер, чем функцию pprint
; посмотрите Language.Haskell.TH.Ppr
модуль.