2013-02-07 13 views
5

में अलग-अलग टाइप किए गए पैरामीटर का उपयोग नहीं कर सकते हैं Type Level Literals के साथ किसी भी प्रकार के प्रकार का उपयोग करके गैर खाली कंटेनर मानों (जैसे प्रेत प्रकारों के साथ) को भेदभाव करने के तरीके के रूप में खेलना।टाइप लेवल लिटलल्स - द्विआधारी फ़ंक्शन

यह अच्छी तरह से काम करता है। (आवश्यक GHC> = 7.6.1)

लेकिन एक द्विआधारी समारोह को परिभाषित करने की कोशिश कर (eq)

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool 

है कि मूल्यों के विभिन्न समूहों मानते हैं, एक संकलन त्रुटि जब यह प्रयोग किया जाता है का संकेत:

प्रकार से मेल नहीं किया जा सका "Just"' with "कुछ भी नहीं" '

{-# LANGUAGE DataKinds, KindSignatures, GADTs, FlexibleInstances #-} 

import GHC.TypeLits 

data TMaybe :: Symbol -> * -> * where 
    TNothing :: TMaybe "Nothing" a 
    TJust :: a -> TMaybe "Just" a 

nonEmpty :: Maybe a -> TMaybe "Just" a 
nonEmpty (Just x) = TJust x 
nonEmpty Nothing = error "invalid nonEmpty data" 

-- this fromJust rejects TNothing at compile time 
fromJust :: (sym ~ "Just") => TMaybe (sym :: Symbol) a -> a 
fromJust (TJust x) = x 

tmbToMaybe :: TMaybe (sym :: Symbol) a -> Maybe a 
tmbToMaybe TNothing = Nothing 
tmbToMaybe (TJust x) = Just x 

mbToTNothing Nothing = TNothing 

mbToTJust (Just x) = TJust x 

instance Eq a => Eq (TMaybe (sym :: Symbol) a) where 
    TNothing == TNothing = True 
    TJust x == TJust y = x == y 
    _ == _ = False -- useless, equal types required 

instance Ord a => Ord (TMaybe (sym :: Symbol) a) where 
    compare TNothing TNothing = EQ 
    compare (TJust x) (TJust y) = Prelude.compare x y 
    compare TNothing _ = LT -- useless, equal types required 
    compare _ TNothing = GT -- useless, equal types required 

instance Functor (TMaybe (sym :: Symbol)) where 
    fmap _ TNothing  = TNothing 
    fmap f (TJust a)  = TJust (f a) 

instance Monad (TMaybe "Just") where 
    (TJust x) >>= k  = k x 

    (TJust _) >> k  = k 

    return   = TJust 
    fail _    = error "can't fail to TNothing" 

-------------------------- 

-- defining eq to admit parameter types with different symbol 

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool 
eq TNothing TNothing = True 
eq (TJust x) (TJust y) = x == y 
eq _ _ = False 

--------------------------- 

-- Test 

main = do 
     print $ fromJust $ TJust (5::Int) -- type-checks 
     -- print $ fromJust TNothing -- as expected, does not type-check 

     -- print $ TNothing == TJust (5::Int) -- as expected, does not type-check, types required equal at function def. 
     print $ TNothing `eq` TJust (5::Int) -- does not type-check either 

उत्तर

9

खैर, अपने प्रकार

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool 

मांग करता है कि दोनों तर्कों का एक ही प्रकार है, इसलिए निश्चित रूप से संकलक TMaybe "Nothing" a और TMaybe "Just" a की तुलना करने के प्रयास को अस्वीकार कर देगा।

आप

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym1 :: Symbol) a -> Bool 

यह संकलित करता है तथा

के प्रकार को बदलते हैं
TNothing `eq` TJust (5::Int) 

False मूल्यांकन करता है। (फिर आपको कई स्थानों पर TNothing एस के प्रकार को स्पष्ट रूप से निर्धारित करने की आवश्यकता है।)

+0

धन्यवाद, इस प्रकार के सामान को छेड़छाड़ करने के साथ, मैंने 'sym' चर पर ध्यान नहीं दिया –

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