You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中是否存在类似:t的类型查询函数或返回类型名的字符串函数?

Haskell: Getting Type Information at Runtime vs. Compile-Time

Great question—this touches on some key quirks of Haskell's static type system and how it interacts with runtime vs. compile-time information. Let's break down your questions one by one:

Can we replicate the :t command inside a Haskell program?

First, it’s important to clarify: :t is a GHCi-specific command, not a function built into the Haskell language itself. It operates during the type-checking phase (either in GHCi or at compile time) to display the static type of an expression.

Haskell uses type erasure by default—meaning type information is stripped away after compilation to keep runtime execution efficient. That means we can’t directly get the full polymorphic type of an expression (like :t id showing id :: a -> a) at runtime. But we can get close with two main approaches:

1. Runtime type information with Typeable

If you enable the Typeable extension (GHC enables this by default in recent versions), you can use the typeOf function from Data.Typeable to get a runtime representation of a concrete type. Pair it with show, and you’ll get a string of the type name.

Example:

import Data.Typeable

main :: IO ()
main = do
  putStrLn $ show (typeOf (5 :: Int))          -- Output: "Int"
  putStrLn $ show (typeOf (Just "hello"))     -- Output: "Maybe [Char]"
  putStrLn $ show (typeOf (\x -> x + 1))      -- Output: "Int -> Int"

A quick caveat: This only works for monomorphic (concrete) types. If you try typeOf id directly, you’ll hit a compile error—Haskell can’t infer a concrete type for the polymorphic id function here. You need to give it a concrete instance, like typeOf (id 5) to get Int -> Int.

2. Compile-time type strings with Template Haskell

If you want the full polymorphic type string (exactly like :t outputs), use Template Haskell to query the type system at compile time. The reify function from Language.Haskell.TH lets you access metadata for types, functions, and values, which you can convert to a string.

Example:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH

-- Gets the type string of 'id' as a compile-time constant
idType :: String
idType = $(stringE . pprint =<< reify 'id)

main :: IO ()
main = putStrLn idType  -- Output: "id :: forall a. a -> a"

This gives you the exact same output as :t id because it’s resolved during compilation, not runtime.

Is there a function that returns a type name as a string?

Absolutely! The combination of show . typeOf (from the Data.Typeable approach above) does exactly this. For custom types, you just need to derive the Typeable instance (GHC can do this automatically with the DeriveTypeable extension, also enabled by default now):

{-# LANGUAGE DeriveTypeable #-}
import Data.Typeable

data User = User String Int deriving (Typeable, Show)

main :: IO ()
main = putStrLn $ show (typeOf (User "Alice" 30))  -- Output: "User"

Why can’t we have a pure Haskell function that does exactly what :t does?

The core issue is phase separation: :t operates in the compiler’s type-checking phase, while regular Haskell functions run in the runtime phase. Haskell’s type system is designed to keep type information separate from runtime values by default—this keeps the language safe and efficient. To bridge this gap, we need opt-in extensions like Typeable (for runtime type info) or Template Haskell (for compile-time type queries) that break this strict separation for specific use cases.

内容的提问来源于stack exchange,提问作者RussAbbott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:45:41