मैं एक आवेदक मज़ेदार पर काम कर रहा हूं जिसमें निष्पादन को "देखने" के लिए एक मोनॉयड शामिल है। हालांकि, कभी-कभी मुझे इस हिस्से की परवाह नहीं है, इसलिए मोनोइड की पसंद अप्रासंगिक है क्योंकि इसे कभी भी उपभोग नहीं किया जाएगा। मैं सरल बना दिया है कि मैं क्या में है:बाधाओं का प्रकार और 'सीमित' बाधाओं वाले परिवारों का प्रकार
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a() where render = const()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
एक भी b
में विभिन्न a
रों को बदलने के लिए प्रयोग किया जाता है। Merge
मेरे वास्तविक मज़ेदार का एक बड़ा सरलीकरण है, लेकिन बिंदु यह है कि इसमें एक प्रकार का परिवार/बाधा शामिल है और इसका मेरा इरादा यह निर्दिष्ट करना है कि Render
ers Merge
आवश्यक है।
अब, मैं करने के लिए "रन" Merge
चाहते हो सकता है, लेकिन त्यागने देखने के लिए, जो की तरह कुछ के लिए समान है:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of() -> 5
लेकिन यह असफल हो जायेगी क्योंकि:
अनुमान नहीं किया जा सका
(Renderer a())
merge
का एक प्रयोग मैं क्योंकि च मेरी monoid रूप ()
चुना है से उत्पन्न होने वाली Orall a
, हमारे पास Render a()
का एक उदाहरण है। तो अगर कहने का कोई तरीका था कि Merge a
का मतलब सिर्फ Render
बाधाओं का संग्रह है तो यह ठीक काम करेगा। बेशक, Merge a
उससे अधिक सामान्य है - यह मनमाने ढंग से बाधाओं को जोड़ सकता है, जो संकलन त्रुटि बताता है।
क्या runFoo
के हस्ताक्षर को बदलने के बिना मैं क्या चाहता हूं?
है 'Renderer' हमेशा वास्तव में शामिल एक' Render'? –
@ टिनक्टरियस - नहीं, आम तौर पर 'Foo' – ocharles
के फ़ील्ड में विशिष्ट प्रकारों की मात्रा पर निर्भर करता है क्या कोई कारण है कि 'मर्ज' में पैरामीटर के रूप में भी' b' नहीं है? –