2015-12-21 5 views
7

मन इस पलटा कार्यक्रम:दो कार्य प्रकार एनोटेशन के साथ संकलित। एक एनोटेशन निकालें - संकलित नहीं करता है। दो हटाएं - दोबारा संकलित करें। क्यूं कर?

{-# LANGUAGE ScopedTypeVariables, RecursiveDo #-} 

import Control.Applicative 
import Control.Monad 
import Control.Monad.IO.Class 
import Prelude hiding (div) 
import Reflex.Dom 
import qualified Data.Map as M 

clickMe :: MonadWidget t m => m (Event t()) 
clickMe = do 
    rec (e,_) <- elAttr' "button" M.empty (display c) 
     c :: Dynamic t Int <- count (domEvent Click e) 
    return $ domEvent Click e 

div :: forall t m a . MonadWidget t m => m a -> m a 
div = elAttr "div" ("style" =: "border : 1px solid black") 

app :: forall t m . MonadWidget t m => m() 
app = div $ do 
    aClicks <- clickMe 
    bClicks <- clickMe 
    a <- count aClicks 
    b <- count bClicks 
    l <- combineDyn (\a b -> replicate (a-b)()) a b 
    simpleList l (const clickMe) 
    return() 

main = mainWidget app 

आप या तो div या app से टाइप टिप्पणी निकालने हैं, तो प्रोग्राम एक विशाल, डरावना प्रकार की त्रुटि के साथ संकलन नहीं होंगे। यदि आप दोनों को हटाते हैं, तो यह फिर से संकलित होगा। प्रोग्रामर के परिप्रेक्ष्य से, यह एक भयानक उपयोगकर्ता अनुभव देता है जब कोई एक अनियंत्रित प्रोग्राम को बढ़ाने की कोशिश कर रहा है। यह कोई एहसास नहीं है कि एक अनियंत्रित शब्द के लिए एक सही प्रकार की एनोटेशन जोड़ना एक कंपाइलर त्रुटि का कारण बनता है, और यह प्रोग्रामर को लगता है कि उसे गलत प्रकार मिल गया है।

This is the error you get by removing div's annotation.

Those are the inferred types.

ऐसा क्यों होता है?

+0

जब आप प्रकारों को हटाते हैं तो अनुमानित प्रकार क्या होते हैं? वे प्रदत्त प्रकारों से तुलना कैसे करते हैं? यह एक अटकलें है लेकिन मुझे लगता है कि अनुमानित या प्रदत्त प्रकारों में से एक सामान्य जेनेरिक नहीं था और इसलिए असंगत प्रदान किया गया। अनुमानित प्रकारों को जोड़ने से सवाल का जवाब देने में मदद मिल सकती है। – concept3d

+2

मैंने अब प्रश्न पर अनुमानित प्रकार शामिल किए हैं, हालांकि मैं उन्हें समझ नहीं सकता क्योंकि मकड़ियों हैं। – MaiaVictor

+2

मोनोमोर्फिज्म प्रतिबंध –

उत्तर

4

यह मोनोमोर्फिज्म प्रतिबंध के कारण है। जब कंपाइलर एक प्रकार के एनोटेशन के बिना शीर्ष-स्तरीय बाध्यकारी टाइप कर रहा है, तो यह उस प्रकार के बाध्यकारी प्रकार को असाइन नहीं करेगा यदि उस प्रकार में कोई बाधा है और फ़ंक्शन में कोई वाक्य रचनात्मक तर्क नहीं है, जो आपके कार्यों के दोनों के मामले में है।

हालांकि, यदि आप न तो प्रकार हस्ताक्षर शामिल करते हैं, तो यह अभी भी संकलित नहीं होता है। आपके मामले में, आपने इसे कुछ अतिरिक्त जानकारी दी है (foo = [app, _] भाग) और किसी कारण से यह एक मोनोमोर्फिक प्रकार चुनना चुना - मुझे नहीं पता कि आपके पर्यावरण के बारे में क्या बदल गया है लेकिन यह मानक व्यवहार नहीं है।

{-# LANGUAGE RankNTypes, KindSignatures, MultiParamTypeClasses, FunctionalDependencies #-} 

module Test where 

import Prelude hiding (div) 

class MonadWidget t (m :: * -> *) | m -> t 

div :: forall t m a . MonadWidget t m => m a -> m a 
div = (undefined :: forall t m a . MonadWidget t m => m a -> m a) 

app :: forall t m . MonadWidget t m => m() 
app = (div (undefined :: forall t m . MonadWidget t m => m()) 
     :: forall t m . MonadWidget t m => m()) 

आप किसी भी प्रकार के हस्ताक्षर, या दोनों बाहर टिप्पणी हैं, तो आप एक त्रुटि के साथ पूरा किया जाएगा:

यहाँ एक सरल मुद्दा आप कर रहे हैं आसवन फ़ाइल है। हालांकि, किसी भी शीर्ष-स्तरीय प्रकार के हस्ताक्षर पर टिप्पणी करें, लेकिन इसे ghc -XNoMonomorphismRestriction Test.hs के साथ चलाएं और यह प्रत्येक कॉन्फ़िगरेशन में सफलतापूर्वक संकलित होगा। Hereareafewtests

+0

धन्यवाद। इस बिंदु पर मुझे लगता है कि अगर मुझे डिफ़ॉल्ट रूप से मोनोमोर्फिज्म प्रतिबंध को अक्षम करना चाहिए। – MaiaVictor

1

रीड बार्टन ने टिप्पणियों में उल्लेख किया है, यह The Dreaded Monomorphism Restriction के कारण है।

यहाँ उदाहरण सरलीकृत है:

foo :: Monad m => m a -> m a 
foo = (>>= return) 

bar :: Monad m => m() 
bar = foo (return()) 

monomorphism प्रतिबंध सक्षम कब और foo के प्रकार हस्ताक्षर टिप्पणी की:

  • GHC foo करने के लिए monomorphic प्रकार आवंटित करने के लिए कोशिश करता है और विफल रहता है, क्योंकि कोई डिफ़ॉल्ट है वहाँ Monad उदाहरण:

(इकाई एम 0) की '>> =' एक उपयोग से उत्पन्न होने के लिए कोई उदाहरण
प्रकार चर 'एम 0' अस्पष्ट

  • का उपयोग कर foobar में एक और त्रुटि जो मैं
  • व्याख्या नहीं कर सकते हो जाता है

'm'
क्योंकि प्रकार चर 'm' से बचने के हैं इसके दायरे

साथ प्रकार 'एम 0' से मेल नहीं किया जा सका 0

{-# LANGUAGE NoMonomorphismRestriction #-} प्रागमा जोड़ना इसे ठीक करता है और क्रमशः प्रकार के हस्ताक्षर जोड़ने की अनुमति देता है।

+0

'जोड़ना {- # LANGUAGE NoMonomorphismRestriction # -} प्राग्मा इसे ठीक करता है और क्रमशः प्रकार हस्ताक्षर जोड़ने की अनुमति देता है।' - क्या यह हमेशा सच है? – MaiaVictor

+0

हां, अगर त्रुटि monomorphism प्रतिबंध के कारण होती है। नकारात्मक तरफ, एमआर को डिफ़ॉल्ट रूप से अक्षम करने से कम साझाकरण हो सकता है, लेकिन यह काफी दुर्लभ स्थिति है। –

+0

[यहां] (http://lambda.jstolarek.com/2012/05/towards-understanding-haskells-monomorphism-restriction/) स्पष्टीकरण है कि एमआर साझा करने को कैसे प्रभावित करता है। –

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