11

GHCi :type コマンドと同じ機能を探しています。

理想的には、次のような署名があります

getStaticType :: a -> String

a = getStaticType (1+2)
-- a = "(Num t) => t"

b = getStaticType zipWith
-- b = "(a -> b -> c) -> [a] -> [b] -> [c]"

(注: これは Data.Dynamic とは関係ありません。コンパイラから推論される静的型が必要なだけです。実際、関数へのすべての呼び出しはコンパイル時に定数としてインライン化できるため、関数にはランタイム実装はまったく必要ありません。 GHCi でできるので、どこかにあると思います)

4

2 に答える 2

20

次のように実行できます。

import Data.Typeable

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

タイプは のインスタンスでなければならないことに注意してくださいTypeable。Haskell言語拡張機能Typeableと.DeriveDataTypeable... deriving (Typeable, ...)

また、ポリモーフィック型はこの方法では識別できないことに注意してください。常に特定の型で関数を呼び出さなければならないため、コンパイルされた Haskell コードを使用して GHCi で取得する多相型情報を取得することはできません。

GHCi が行う方法は、GHC API を使用して、型情報を含む中間 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モジュールを見てください。

于 2012-05-01T15:11:44.750 に答える
1

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
于 2014-09-19T17:41:52.000 に答える