2011-11-06 23 views
6

यहाँ मैं क्या आपके पास यह है प्रकार सुरक्षा प्राप्त करने के लिए:variadic सूची निर्माता, कैसे सही प्रकार के लिए डिफ़ॉल्ट और

{-# LANGUAGE MultiParamTypeClasses 
      , FlexibleInstances #-} 

class ListResultMult r a where 
    lstM :: a -> [a] -> r 

listM :: ListResultMult r a => a -> r 
listM a = lstM a [] 


instance ListResultMult r a => ListResultMult (a -> r) a where 
    lstM a as x = lstM x $ a:as 

instance ListResultMult [a] a where 
    lstM a as = reverse $ a:as 

यहाँ यह कैसे काम करता है:

> listM 'a' 'b' 'c' :: String 
"abc" 
> putStrLn $ listM 'a' 'b' 'c' 
abc 
> listM (1::Int) (2::Int) :: [Int] 
[1,2] 

यह इस प्रकार से

विफल रहता है
> sum $ listM 1 2 
No instance for (ListResultMult (a2 -> [a0]) a1) ... 
> listM 1 :: [Int] 
No instance for (ListResultMult [Int] a0) ... 

printf के साथ तुलना:

instance Show a => ListResultMult (IO()) a where 
    lstM a as = print . reverse $ a:as 

> listM "foo" "bar" -- boo 
No instance for (ListResult t0 [Char]) ... 
> printf "%s %s" "foo" "bar" 
foo bar 
> listM "foo" "bar" :: IO() -- yay 
["foo","bar"] 

प्रकार unsafety:

  • प्रकार सुरक्षा:

    > :t listM 2 "foo" 
    Some weird type is actually inferred 
    

    तो यहाँ मुझे क्या करना चाहते हैं। मैंने सोचा कि जब मैंने ListResultMult r a => ListResultMult (a -> r) a और ListResultMult [a] a परिभाषित किया है, तो यह आपको केवल सजातीय सूचियां बनाने की अनुमति देगा, और जब आप नहीं करते हैं तो एक प्रकार की त्रुटि देखें। ऐसा क्यों नहीं किया?

  • डिफ़ॉल्ट। मुझे कोई संकेत नहीं है कि listM 1 :: [Int] के साथ अजीबता क्या चल रही है। क्या हो रहा है?

उत्तर

6

टाइप फ़ंक्शंस केवल इस समस्या के लिए टिकट की तरह लगते हैं। यहां एक नमूना फ़ाइल है:

{-# LANGUAGE TypeFamilies #-} 

class ListResultMult r where 
    type Elem r 
    lstM :: Elem r -> [Elem r] -> r 

listM a = lstM a [] 

instance (ListResultMult r, Elem r ~ a) => ListResultMult (a -> r) where 
    type Elem (a -> r) = a 
    lstM a as x = lstM x (a:as) 

instance ListResultMult [a] where 
    type Elem [a] = a 
    lstM a as = reverse (a:as) 

यहाँ GHCi में अपने उदाहरण हैं:

*Main> listM 'a' 'b' 'c' :: String 
"abc" 
*Main> putStrLn $ listM 'a' 'b' 'c' 
abc 
*Main> listM 1 2 :: [Int] 
[1,2] 
*Main> sum $ listM 1 2 
3 
*Main> listM 1 :: [Int] 
[1] 
*Main> :t listM 'a' True 

<interactive>:1:7: 
    Couldn't match type `Bool' with `Char' 
    In the first argument of `listM', namely 'a' 
    In the expression: listM 'a' True 
*Main> :t listM 2 "foo" 

<interactive>:1:7: 
    No instance for (Num [Char]) 
     arising from the literal `2' 
    Possible fix: add an instance declaration for (Num [Char]) 
    In the first argument of `listM', namely `2' 
    In the expression: listM 2 "foo" 
+0

प्रकार सुरक्षा * और * समझदार चूक! इसने पूरी तरह से सवाल का जवाब दिया, साथ ही संयोग से [मेरे अन्य प्रश्न] का उत्तर दिया [http://stackoverflow.com/questions/8031320)। :) –

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

  • कोई संबंधित समस्या नहीं^_^