मेरे पास कक्षा Cyc c r
है जिसमें c m r
फ़ॉर्म के डेटा के लिए फ़ंक्शन हैं, जहां m
एक प्रेत प्रकार है। उदाहरण के लिए,एक डिक्टरी को एक बाधा में बदलना
class Cyc c r where
cyc :: (Foo m, Foo m') => c m r -> c m' r
मैं m
एक वर्ग पैरामीटर नहीं कर के लिए अच्छे कारणों की क्या ज़रूरत है। इस उदाहरण के प्रयोजनों के लिए, प्राथमिक कारण यह है कि यह कार्यों पर बाधाओं की संख्या को कम करता है। मेरे वास्तविक उदाहरण में, इस इंटरफ़ेस के लिए एक अधिक आकर्षक आवश्यकता यह है कि मैं बदलते और छिपे हुए प्रेत प्रकारों के साथ काम करता हूं, इसलिए यह इंटरफ़ेस मुझे किसी भी प्रेत प्रकार के लिए Cyc
बाधा प्राप्त करने देता है।
उस विकल्प का एक नकारात्मक पक्ष यह है कि मैं Num (c m r)
Cyc
की सुपरक्लस बाधा नहीं बना सकता। मेरा इरादा यह है कि c m r
(Cyc c r, Foo m)
जब भी Num
होना चाहिए। वर्तमान समाधान बहुत कष्टप्रद है: मैं कक्षा Cyc
witNum :: (Foo m) => c m r -> Dict (Num (c m r))
जो तरह-की ही बात सिद्ध करने के लिए विधि गयी। अब जब मैं एक समारोह है कि एक सामान्य Cyc
लेता है और एक Num (c m r)
बाधा की जरूरत है, मैं लिख सकते हैं:
foo :: (Cyc c r, Foo m) => c m r -> c m r
foo c = case witNum c of
Dict -> c*2
पाठ्यक्रम के
मैं foo
करने के लिए एक Num (c m r)
बाधा जोड़ सकता है, लेकिन मैं संख्या को कम करने की कोशिश कर रहा हूँ बाधाओं, याद है? (Cyc c r, Foo m)
को Num (c m r)
बाधा को इंगित करना है (और मुझे अन्य प्रयोजनों के लिए Cyc c r
और Foo m
की आवश्यकता है), इसलिए मैं Num
बाधा को भी लिखना नहीं चाहता हूं।
इस प्रश्न को लिखने की प्रक्रिया में, मुझे इसे पूरा करने के लिए एक बेहतर (?) तरीका मिला, लेकिन इसकी अपनी कमियां हैं।
मॉड्यूल फू:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, ScopedTypeVariables #-}
module Foo where
import Data.Constraint
class Foo m
class Cyc c r where
cyc :: (Foo m, Foo m') => c m r -> c m' r
witNum :: (Foo m) => c m r -> Dict (Num (c m r))
instance (Foo m, Cyc c r) => Num (c m r) where
a * b = case witNum a of
Dict -> a * b
fromInteger a = case witNum (undefined :: c m r) of
Dict -> fromInteger a
-- no Num constraint and no Dict, best of both worlds
foo :: (Foo m, Cyc c r) => c m r -> c m r
foo = (*2)
मॉड्यूल बार: इस दृष्टिकोण मुझे सब कुछ मैं के लिए देख रहा हूँ हो जाता है
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, OverlappingInstances #-}
module Bar where
import Foo
import Data.Constraint
data Bar m r = Bar r deriving (Show)
instance (Num r) => Cyc Bar r where
witNum _ = Dict
instance (Num r, Foo m) => Num (Bar m r) where
(Bar a) * (Bar b) = Bar $ a*b
fromInteger = Bar . fromInteger
instance Foo()
bar :: Bar() Int
bar = foo 3
है, यह कमजोर लगती है। मेरा मुख्य चिंताएं हैं:
- मैं मॉड्यूल
Foo
मेंNum
के लिए सामान्य उदाहरण सिर से सावधान कर रहा हूँ। - किसी भी अतिव्यापी उदाहरणों
Foo
में आयात कर रहे हैं, मैं अचानकIncoherentInstances
की जरूरत है याfoo
परNum
बाधा स्थगित करने उदाहरण चयन क्रम के लिए।
वहाँ एक वैकल्पिक तरीका हर समारोह है कि जरूरत Num (c m r)
कि इन कमियां में से किसी से बचा जाता है में Dict
का उपयोग कर से बचने के लिए है?
यदि आप [बाधाओं] का उपयोग कर रहे हैं (https://hackage.haskell.org/package/constraints) 'witNum' को परिभाषित करने का मूर्ख तरीका' witNum :: Foo m: - Num (cmr) 'होगा जो आप उदाहरण के साथ deconstruct 'foo = case witNum :: Foo m: - उप डिक्ट की संख्या (सी एम आर) -> (* 2)' (जो कोई सुंदर नहीं है)। – Cirdec
कि 'न्यूम (सी एम आर)' इंस्टेंस हेड * आपको डराएगा। – dfeuer
लेकिन मैं इसके बारे में * क्या करूँ? :-) – crockeea