2015-07-16 12 views
6

यहां एक अनियमित लैम्ब्डा कैलकुस है जिसका शब्द उनके मुक्त चर द्वारा अनुक्रमित किया गया है। मैं टाइप-स्तरीय तारों के सिंगलटन मानों के लिए singletons लाइब्रेरी का उपयोग कर रहा हूं।जीएचसी मेरे प्रकार के परिवार को क्यों नहीं कम करेगा?

{-# LANGUAGE DataKinds #-} 
{-# LANGUAGE GADTs #-} 
{-# LANGUAGE PolyKinds #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE UndecidableInstances #-} 

import Data.Singletons 
import Data.Singletons.TypeLits 

data Expr (free :: [Symbol]) where 
    Var :: Sing a -> Expr '[a] 
    Lam :: Sing a -> Expr as -> Expr (Remove a as) 
    App :: Expr free1 -> Expr free2 -> Expr (Union free1 free2) 

Var एक नि: शुल्क चर प्रस्तुत करता है। एक लैम्ब्डा अमूर्तता एक चर को बांधती है जो शरीर में मुक्त दिखाई देती है (यदि कोई है जो मेल खाता है)। अनुप्रयोग अभिव्यक्ति के दो हिस्सों के मुक्त चरों में शामिल होते हैं, डुप्लिकेट को हटाते हैं (इसलिए x y के निशुल्क चर x और y हैं, जबकि x x के निशुल्क चर x हैं)।

type family Remove x xs where 
    Remove x '[] = '[] 
    Remove x (x ': xs) = Remove x xs 
    Remove x (y ': xs) = y ': Remove x xs 

type family Union xs ys where 
    Union xs ys = Nub (xs :++ ys) 

type family xs :++ ys where 
    '[] :++ ys = ys 
    (x ': xs) :++ ys = x ': (xs :++ ys) 

type family Nub xs where 
    Nub xs = Nub' '[] xs 

type family Nub' seen xs where 
    Nub' seen '[] = '[] 
    Nub' seen (x ': xs) = If (Elem x seen) (Nub' seen xs) (Nub' (x ': seen) (x ': xs)) 

type family If c t f where 
    If True t f = t 
    If False t f = f 

type family Elem x xs where 
    Elem x '[] = False 
    Elem x (x ': xs) = True 
    Elem x (y ': xs) = Elem x xs 

मैं इस इंटरैक्टिव प्रॉम्प्ट पर बाहर का परीक्षण किया:

ghci> :t Var (sing :: Sing "x") 
Var (sing :: Sing "x") :: Expr '["x"] -- good 
ghci> :t (Lam (sing :: Sing "x") (Var (sing :: Sing "x"))) 
(Lam (sing :: Sing "x") (Var (sing :: Sing "x"))) 
    :: Expr (Remove "x" '["x"]) -- not so good 

मैं जानने के लिए कि पहचान समारोह \x. x के प्रकार Expr (Remove "x" '["x"]), नहीं Expr '[] है हैरान था मैं उन प्रकार परिवारों बाहर लिखा था। जीएचसी प्रकार परिवार Remove का मूल्यांकन करने के इच्छुक नहीं है। मैं एक छोटे से अधिक प्रयोग किया और पता चला कि यह असल मेरी प्रकार परिवार के साथ एक समस्या नहीं है - GHC इस मामले में यह कम करने के लिए खुश है:

ghci> :t (Proxy :: Proxy (Remove "x" '["x"])) 
(Proxy :: Proxy (Remove "x" '["x"])) :: Proxy '[] 

तो: क्यों नहीं GHC '[] लिए कम हो जाएगा Remove "x" '["x"] जब मैं मेरे जीएडीटी के प्रकार से पूछताछ करें? आम तौर पर, जब टाइपर टाइप प्रकार का प्रकार किसी प्रकार का परिवार मूल्यांकन करेगा? क्या ऐसे व्यवहार हैं जो मैं अपने व्यवहार से आश्चर्यचकित होने से बचने के लिए उपयोग कर सकता हूं?

+4

मैंने पढ़ा "क्यों GHC मेरे परिवार को कम नहीं करेंगे:

λ *Main > :t (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) :: Expr (Remove "x" '["x"]) λ *Main > :t (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) :: Expr '[] (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) :: Expr '[] :: Expr '[] λ *Main > :t (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) :: Expr '["x"] <interactive>:1:2: Couldn't match type ‘'[]’ with ‘'["x"]’ Expected type: Expr '["x"] Actual type: Expr (Remove "x" '["x"]) In the expression: (Lam (Proxy :: Proxy "x") (Var (Proxy :: Proxy "x"))) :: Expr '["x"] 

मैं परिभाषाएँ बदल तो वहाँ एकमात्र पुस्तकालय पर निर्भरता नहीं है (आसान तदर्थ में परीक्षण करने के लिए)? "और यह बहुत क्रूर लग रहा था। –

+1

@JoachimBreitner यहां तक ​​कि सबसे अच्छे कंपाइलर्स आप जो भी चाहते हैं वह सब कुछ नहीं कर सकते हैं –

+1

मुझे https://wiki.haskell.org/GHC/Type_families#Closed_family_simplification के आधार पर 'निकालें' में ओवरलैपिंग परिभाषाओं पर संदेह होगा। आपको शायद एक बाधा की आवश्यकता होगी, यह देखते हुए कि प्रकार असमान – phadej

उत्तर

2

यह काम करता है। जीएचसी सिर्फ आलसी लगता है।

{-# LANGUAGE TypeOperators, DataKinds, TypeFamilies, GADTs #-} 

import Data.Proxy 
import GHC.TypeLits 

type family Remove (x :: Symbol) (xs :: [Symbol]) where 
    Remove x '[] = '[] 
    Remove x (x ': xs) = Remove x xs 
    Remove x (y ': xs) = y ': Remove x xs 

data Expr (free :: [Symbol]) where 
    Var :: KnownSymbol a => Proxy a -> Expr '[a] 
    Lam :: KnownSymbol a => Proxy a -> Expr as -> Expr (Remove a as) 
-- App :: Expr free1 -> Expr free2 -> Expr (Union free1 free2) 
+0

हैं, ऐसा लगता है कि 'निकालें "x"' [x x]] ''[]' के साथ एकीकृत करता है, लेकिन इसे सामान्य नहीं करता है, कम से कम नहीं इंटरैक्टिव प्रॉम्प्ट। कोई विचार क्यों? "जीएचसी सिर्फ आलसी लगता है" निश्चित रूप से सच है, लेकिन मैं एक और अधिक रोशनी स्पष्टीकरण की उम्मीद कर रहा था! –

+0

मैं 100% निश्चित नहीं हूं। https://wiki.haskell.org/GHC/Type_families#Closed_family_simplification इस बारे में अनुभाग है कि जीएडीटी कैसे चीजों को कठिन बनाते हैं। तो शायद * आलसी * नहीं, लेकिन * सावधान * (जो कोई भी वही समझ सकता है :))। – phadej

संबंधित मुद्दे