2012-05-01 8 views
11

मैं एक ऐसा फ़ंक्शन ढूंढ रहा हूं जो GHCi: टाइप कमांड करता है।हास्केल: एक अभिव्यक्ति का स्थैतिक प्रकार प्राप्त करना

आदर्श रूप में, ऐसा लगता है जैसे

getStaticType :: a -> String 

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

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

(नोट एक हस्ताक्षर कुछ है जाएगा:।। इस Data.Dynamic साथ मैं सिर्फ स्थिर प्रकार संकलक से अनुमान लगाया चाहते लेना देना नहीं है वास्तव में समारोह wouldn ' टी, सब पर एक क्रम कार्यान्वयन की जरूरत के रूप में यह करने के लिए सभी कॉल्स संकलन समय पर स्थिरांक के रूप में inlined किया जा सकता है मैं, यह मानते हुए कर रहा हूँ इसे कहीं मौजूद है के बाद से GHCi यह कर सकते हैं)

उत्तर

20

आप इसे इस तरह कर सकते हैं:।

import Data.Typeable 

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

ध्यान दें कि प्रकार Typeable का एक उदाहरण होना चाहिए। आप स्वचालित रूप से DeriveDataTypeable हास्केल भाषा एक्सटेंशन और ... deriving (Typeable, ...) का उपयोग कर प्राप्त कर सकते हैं।

यह भी ध्यान दें कि पॉलिमॉर्फिक प्रकारों को इस तरह से पहचाना नहीं जा सकता है; आपको हमेशा विशिष्ट प्रकार के साथ फ़ंक्शन को कॉल करना होगा, ताकि आप कभी भी उस पॉलिमॉर्फिक प्रकार की जानकारी प्राप्त न कर सकें जिसे आप GHCi में संकलित हास्केल कोड के साथ प्राप्त करते हैं।

जिस तरह से जीएचसीआई करता है वह यह है कि यह मध्यस्थ हास्केल सार वाक्यविन्यास पेड़ (एएसटी) का विश्लेषण करने के लिए जीएचसी एपीआई का उपयोग करता है जिसमें टाइप जानकारी होती है। जीएचसीआई में एक ही प्रतिबंधित वातावरण नहीं है जो आपके ठेठ संकलित हास्केल प्रोग्राम करता है; यह अपने पर्यावरण के बारे में अधिक जानकारी प्राप्त करने के लिए बहुत सी चीजें कर सकता है।

टेम्पलेट हास्केल के साथ, आप इसे ऐसा कर सकते हैं; तब

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 मॉड्यूल पर एक नज़र डालें।

+0

उपयोग स्वयं का दस्तावेजीकरण कोड और प्रवेश के लिए है। यह बहुत बुरा है, यह संभव नहीं है, ऐसा लगता है कि संकलक में "जादू कार्य" के रूप में लागू करना मुश्किल होगा, जिसमें पहले से ही सभी जानकारी है। – drwowe

+5

टीबीएच, हास्केल काफी दृढ़ता से "एंटी-जादू" है। –

+0

@drwowe सही है - एक कंपाइलर में कार्यान्वित करना काफी आसान होगा। यह एक प्रकार का संकलन समय समारोह होगा जैसे * आकार में * सी – Ingo

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