Вопрос по ghc, haskell, types – Haskell: получение статического типа выражения

11

Я ищу функцию, которая делает то же, что и команда GHCi: type.

В идеале это было бы что-то вроде подписи

<code>getStaticType :: a -> String

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

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

(Примечание: это не имеет ничего общего с Data.Dynamic. Я просто хочу, чтобы статический тип был выведен из компилятора. Фактически функция вообще не нуждается в реализации во время выполнения, поскольку все вызовы к ней могут быть встроены как константы при компиляции. время. Я предполагаю, что оно где-то существует, поскольку GHCi может это сделать)

Ваш Ответ

2   ответа
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
20

import Data.Typeable

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

Обратите внимание, что тип должен быть экземпляромTypeable, Вы можете получитьTypeable автоматически используяDeriveDataTypeable Расширение языка Haskell и... deriving (Typeable, ...).

Также обратите внимание, что полиморфные типы не могут быть идентифицированы таким образом; Вы всегда должны вызывать функцию сspecific type, так что вы никогда не сможете получить ту полиморфную информацию о типе, которую вы получаете в 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

Затем вdifferent module (очень важно), вы можете сделать следующее:

{-# 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 модуль.

TBH, Haskell довольно сильно "антимагический".
@drwowe является правильным - такое было бы довольно легко реализовать в компиляторе. Это будет своего рода функция времени компиляции, какsizeof в С.
Точно так же, как идея его использования может заключаться в том, чтобы реализовать его как экземпляр для Show для функций.
Используется для самодокументирования кода и регистрации. Это слишком плохо, это невозможно, кажется, что это было бы тривиально для реализации в качестве «магической функции». в компиляторе, который уже имеет всю информацию. drwowe

Похожие вопросы