मैं एक अलग दृष्टिकोण के साथ @Daniel वैगनर के उत्कृष्ट जवाब का विस्तार करना चाहते हैं: (यदि वहाँ एक है), एक मान्य प्रकार लौटने typechecking के बजाय एक टाइप किया अभिव्यक्ति है कि तो गारंटी है कि हम इसे मूल्यांकन कर सकते हैं वापसी (चूंकि बस टाइप किए गए लैम्ब्डा कैलकुस दृढ़ता से सामान्यीकृत होते हैं)। मूल विचार यह है check ctx t e
रिटर्न Just (ctx |- e :: t)
e
iff कुछ संदर्भ ctx
में t
में टाइप किया जा सकता है, और फिर कुछ टाइप किया अभिव्यक्ति ctx |- e :: t
दिया है हम सही प्रकार से कुछ Env
ironment में यह मूल्यांकन कर सकते हैं।
कार्यान्वयन
मैं एकमात्र का उपयोग किया जाएगा check :: (ctx :: [Type]) -> (a :: Type) -> Term -> Maybe (TTerm ctx a)
की पाई प्रकार, हम हर GHC विस्तार और पानी के नल को चालू करने की आवश्यकता होगी, जिसका मतलब है अनुकरण करने के लिए:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds, KindSignatures, TypeFamilies, TypeOperators #-}
{-# LANGUAGE TemplateHaskell #-} -- sigh...
import Data.Singletons.Prelude
import Data.Singletons.TH
import Data.Type.Equality
पहली बिट है untyped प्रतिनिधित्व, सीधे @Daniel वैगनर के जवाब से:
data Type = Base
| Arrow Type Type
deriving (Show, Eq)
data Term = Const
| Var Int
| Lam Type Term
| App Term Term
deriving Show
लेकिन हम भी इन प्रकार के अर्थ विज्ञान की व्याख्या से दे देंगे Base
()
के रूप में और Arrow t1 t2
रूप t1 -> t2
:
type family Interp (t :: Type) where
Interp Base =()
Interp (Arrow t1 t2) = Interp t1 -> Interp t2
de Bruijn विषय के साथ रखने के लिए, संदर्भों प्रकार की सूची है, और चर संदर्भ के सूचकांकों हैं। एक संदर्भ प्रकार के वातावरण को देखते हुए, हम मूल्य प्राप्त करने के लिए एक चर सूचकांक देख सकते हैं। ध्यान दें कि lookupVar
कुल कार्य है।
data VarIdx (ts :: [Type]) (a :: Type) where
Here :: VarIdx (a ': ts) a
There :: VarIdx ts a -> VarIdx (b ': ts) a
data Env (ts :: [Type]) where
Nil :: Env '[]
Cons :: Interp a -> Env ts -> Env (a ': ts)
lookupVar :: VarIdx ts a -> Env ts -> Interp a
lookupVar Here (Cons x _) = x
lookupVar (There v) (Cons _ xs) = lookupVar v xs
ठीक है हमारे पास वास्तव में कुछ कोड लिखने के लिए सभी बुनियादी ढांचे हैं। अब तक तो अच्छा
data TTerm (ctx :: [Type]) (a :: Type) where
TConst :: TTerm ctx Base
TVar :: VarIdx ctx a -> TTerm ctx a
TLam :: TTerm (a ': ctx) b -> TTerm ctx (Arrow a b)
TApp :: TTerm ctx (Arrow a b) -> TTerm ctx a -> TTerm ctx b
eval :: Env ctx -> TTerm ctx a -> Interp a
eval env TConst =()
eval env (TVar v) = lookupVar v env
eval env (TLam lam) = \x -> eval (Cons x env) lam
eval env (TApp f e) = eval env f $ eval env e
: सबसे पहले, चलो एक साथ एक (! कुल) मूल्यांकनकर्ता के साथ, Term
के द्वारा लिखा गया प्रतिनिधित्व परिभाषित करते हैं। eval
अच्छा & कुल है क्योंकि इसका इनपुट केवल टाइप किए गए लैम्ब्डा कैलकुस के अच्छी तरह से टाइप की गई शर्तों का प्रतिनिधित्व कर सकता है। इसलिए @ डैनियल के मूल्यांकनकर्ता के काम का हिस्सा टाइप किए गए एक के प्रतिनिधित्व के परिवर्तन में किया जाना चाहिए।
infer
के पीछे मूल विचार है कि प्रकार निष्कर्ष सफल होता है, यह रिटर्न Just $ TheTerm t e
, जहां t
e
के प्रकार का एक Sing
LETON गवाह है।
$(genSingletons [''Type])
$(singDecideInstance ''Type)
-- I wish I had sigma types...
data SomeTerm (ctx :: [Type]) where
TheTerm :: Sing a -> TTerm ctx a -> SomeTerm ctx
data SomeVar (ctx :: [Type]) where
TheVar :: Sing a -> VarIdx ctx a -> SomeVar ctx
-- ... and pi ones as well
infer :: Sing ctx -> Term -> Maybe (SomeTerm ctx)
infer _ Const = return $ TheTerm SBase TConst
infer ts (Var n) = do
TheVar t v <- inferVar ts n
return $ TheTerm t $ TVar v
infer ts (App f e) = do
TheTerm t0 e' <- infer ts e
TheTerm (SArrow t0' t) f' <- infer ts f
Refl <- testEquality t0' t0
return $ TheTerm t $ TApp f' e'
infer ts (Lam ty e) = case toSing ty of
SomeSing t0 -> do
TheTerm t e' <- infer (SCons t0 ts) e
return $ TheTerm (SArrow t0 t) $ TLam e'
inferVar :: Sing ctx -> Int -> Maybe (SomeVar ctx)
inferVar (SCons t _) 0 = return $ TheVar t Here
inferVar (SCons _ ts) n = do
TheVar t v <- inferVar ts (n-1)
return $ TheVar t $ There v
inferVar _ _ = Nothing
उम्मीद है कि अंतिम चरण स्पष्ट है: के बाद से हम केवल एक दिया प्रकार पर एक अच्छी तरह से टाइप किया अवधि मूल्यांकन कर सकते हैं (के बाद से है कि क्या हमें अपने हास्केल एम्बेडिंग के प्रकार देता है), हम प्रकार check
में प्रकार बारी infer
खिलाडि़यों ing:
check :: Sing ctx -> Sing a -> Term -> Maybe (TTerm ctx a)
check ctx t e = do
TheTerm t' e' <- infer ctx e
Refl <- testEquality t t'
return e'
उदाहरण सत्र
के GHCi में हमारे कार्यों को कोशिश करते हैं:
λ» :set -XStandaloneDeriving -XGADTs
λ» deriving instance Show (VarIdx ctx a)
λ» deriving instance Show (TTerm ctx a)
λ» let id = Lam Base (Var 0) -- \x -> x
λ» check SNil (SBase `SArrow` SBase) id
Just (TLam (TVar Here))
λ» let const = Lam Base $ Lam Base $ Var 1 -- \x y -> x
λ» check SNil (SBase `SArrow` SBase) const
Nothing -- Oops, wrong type
λ» check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
Just (TLam (TLam (TVar Here)))
λ» :t eval Nil <$> check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
eval Nil <$> check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
:: Maybe (() ->() ->())
-- Note that the `Maybe` there comes from `check`, not `eval`!
λ» let Just const' = check SNil (SBase `SArrow` (SBase `SArrow` SBase)) const
λ» :t eval Nil const'
eval Nil const' ::() ->() ->()
λ» eval Nil const'()()
()
क्या आप जो भी करने की कोशिश कर रहे हैं उसका पूरा उदाहरण शामिल कर सकते हैं? शायद कुछ शब्द, एक वाक्य जो चेक टाइप करता है, और एक वाक्य जो जांच नहीं करता है कि आप एक संकलन समय के बजाय विफलता के लिए रनटाइम मान चाहते हैं? यदि आप एक प्रकार तक पहुंचने के लिए "उन्हें गठबंधन करने का कोई तरीका" है, तो आप यह जानना चाहते हैं कि आप किसी प्रकार की खोज की तलाश में हैं जो वर्तमान में हास्केल के प्रकार चेकर से अधिक है (एक ऐसा उपकरण है जो "जीनी" इसके नाम पर, लेकिन मुझे अभी इसके लिए कोई लिंक नहीं मिल रहा है)। – Cirdec
आह हाँ, उपकरण [djinn] है (https://hackage.haskell.org/package/djinn)। इसमें उसमें से संबंधित है, टाइप किए गए ऑब्जेक्ट्स का एक छोटा सा सेट - इकाई '()', टुपल्स '(,)', और कार्यों के लिए लैम्ब्डा कन्स्ट्रक्टर, यह किसी ऑब्जेक्ट को किसी दिए गए प्रकार से कम करने का प्रयास करता है। एक [संबंधित प्रश्न] है (http://stackoverflow.com/questions/10205793/given-a-haskell-type-ignature-is-it-possible-to-generate-the-code-automaticall) से हास्केल कोड को कम करने के बारे में प्रकार के। – Cirdec
मैं आपके लक्ष्य को बिल्कुल समझ नहीं सकता। विशेष रूप से, चाहे आप टाइपिंग जांच को स्थिर रूप से (अपने प्रोग्राम को चलाने से पहले) या गतिशील रूप से (रन टाइम पर) करना चाहते हैं। एक पहुंचने योग्य 'के बारे में आपका अंतिम बयान यह इंगित करता है कि आप गतिशील जांच चाहते हैं, लेकिन आपको इसे स्पष्ट करना चाहिए। – chi