2012-10-03 19 views
7

मैं कुछ काल्पनिक प्रकार है:बहुरूपी बाधा

{-# LANGUAGE DeriveFunctor #-} 

data T a = T a deriving (Functor) 

... और उस प्रकार कुछ काल्पनिक वर्ग के उदाहरण है:

class C t where 
    toInt :: t -> Int 

instance C (T a) where 
    toInt _ = 0 

मैं कैसे एक समारोह बाधा में व्यक्त कर सकते हैं T a है कि सभी a के लिए कुछ कक्षा का एक उदाहरण? Intuitively

f t = toInt $ fmap Left t 

, मैं ऊपर समारोह सभी a के लिए T a पर toInt काम करता है के बाद से काम करने की उम्मीद है, लेकिन मैं व्यक्त नहीं कर सकते कि प्रकार में:

उदाहरण के लिए, निम्नलिखित समारोह पर विचार करें। यह काम नहीं करता:

f :: (Functor t, C (t a)) => t a -> Int 

... क्योंकि जब हम fmap लागू प्रकार Either a b बन गया है। मैं का उपयोग कर इसे ठीक नहीं कर सकते हैं:

f :: (Functor t, C (t (Either a b))) => t a -> Int 

... क्योंकि b एक सार्वभौमिक मात्रा निर्धारित चर का प्रतिनिधित्व नहीं करता। न ही मैं कह सकता हूँ:

f :: (Functor t, C (t x)) => t a -> Int 

... या forall x का उपयोग जो बताते हैं कि बाधा सभी x लिए मान्य है।

तो मेरा सवाल यह है कि अगर ऐसा कहने का कोई तरीका है कि एक बाधा इसके कुछ प्रकार के चर पर बहुलक है।

+0

मुझे लगता है कि 'की तरह क्लास सी टी कुछ जहां toInt :: टा -> Int' काम नहीं करेगा, और आप की जरूरत' C' तरह का होना करने के लिए '* -> बाधा '? क्या दयालु बहुलवाद यहां मदद करेगा? –

+0

@ सीए.एमसीकैन मेरे मन में ठोस प्रकार का कन्स्ट्रक्टर 'पाइप' से 'प्रॉक्सी' है और कंक्रीट क्लास 'मोनाड' है। मैं प्रॉक्सी-जैसी प्रकारों के लिए टाइप-क्लासिंग यूटिलिटी फ़ंक्शन हूं, यही कारण है कि बाधा वहां है। आपके सुझाव के बाद, मैं 'प्रॉक्सी' प्रकार के कन्स्ट्रक्टर के आकार के लिए विशिष्ट 'मोनाडपी' वर्ग परिभाषित करता हूं और इसके बजाय एक बाधा के रूप में उपयोग करता हूं। नुकसान यह है कि यदि उपयोगकर्ता प्रॉक्सी उपयोगिता कार्यों को प्रॉक्सी-जैसे प्रकार में पॉलिमॉर्फिक लिखना चाहते हैं, तो उन्हें इसके बजाय 'मोनाडपी' का उपयोग करने के लिए नोटेशन को दोबारा जोड़ना होगा। –

+2

आप इसे सीधे नहीं कर सकते हैं, लेकिन रोमन के जवाब में अनुकरण करना संभव है। यहां प्रासंगिक जीएचसी टिकट है: http://hackage.haskell.org/trac/ghc/ticket/2893 – glaebhoerl

उत्तर

6

constraints पैकेज का उपयोग करना:

{-# LANGUAGE FlexibleContexts, ConstraintKinds, DeriveFunctor, TypeOperators #-} 

import Data.Constraint 
import Data.Constraint.Forall 

data T a = T a deriving (Functor) 

class C t where 
    toInt :: t -> Int 

instance C (T a) where 
    toInt _ = 0 

f :: ForallF C T => T a -> Int 
f t = (toInt $ fmap Left t) \\ (instF :: ForallF C T :- C (T (Either a b))) 
+3

यह 'फोरेलएफ' के स्रोत को देखने के लायक है, अगर केवल प्रशंसा करने के लिए कि कितना सरल/बदसूरत/पीछे विचार यह है :) – copumpkin

+0

@copumpkin: मुझे वास्तव में इसके बारे में एक सवाल है - http://stackoverflow.com/questions/12728159/how-does-the-constraints-package-work –

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