2016-01-12 6 views
6

मुझे लगता है कि एक भी फ़ील्ड में कोई कस्टम डेटा प्रकार परिभाषित:मैं "टाइपपीफ" -स्टाइल डेटा प्रकारों से कम से कम बॉयलरप्लेट के साथ कैसे निपट सकता हूं?

import Data.Set (Set) 

data GraphEdge a = GraphEdge (Set a) 

को परिभाषित करना मेरे अपने प्रकार अधिक शब्दार्थ सही लगता है लेकिन यह मेरी कार्यों में बॉयलरप्लेट का एक बहुत की ओर जाता है। किसी भी समय मैं चाहता हूँ निर्मित Set कार्यों मैं आंतरिक सेट उपहार में और बाद में करने के लिए है का उपयोग करने के लिए यह हर दूसरे पट्टी बदल:

import Data.Set (map) 

modifyItemsSomehow :: Ord a => GraphEdge a -> GraphEdge a 
modifyItemsSomehow (GraphEdge items) = GraphEdge $ Set.map someFunction items 

यह एक रिकार्ड बनाकर थोड़ा सुधार किया जा सकता,

import Data.Set (Set, map) 

data GraphEdge a = GraphEdge { unGraphEdge :: Set a } 

modifyItemsSomehow = GraphEdge . map someFunction . unGraphEdge 

की तरह लेकिन यह अभी भी आदर्श से बहुत दूर लगता है। उपयोगकर्ता द्वारा परिभाषित डेटा प्रकार से निपटने के दौरान इस तरह के बॉयलरप्लेट को संभालने का सबसे बेवकूफ तरीका क्या है जिसमें एक फ़ील्ड होता है?

+7

किसी भी कारण से आप 'newtype' के बजाय' डेटा' का उपयोग कर रहे हैं? – Carl

+0

@ करल नोप, बस अज्ञानता :-) – bdesham

उत्तर

5

किसी और चीज से पहले, आपको एकल क्षेत्र एकल-कन्स्ट्रक्टर प्रकारों के लिए newtype का उपयोग करना सुनिश्चित करना चाहिए। data रनटाइम ओवरहेड और अतिरिक्त आलस्य प्रस्तुत करता है, और हमें निम्नलिखित तकनीकों में से पहले दो का उपयोग करने से रोकता है।

सबसे पहले, आप GeneralizedNewtypeDeriving का उपयोग जब संभव कर सकते हैं:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

newtype Foo a = Foo a deriving (Eq, Show, Ord, Num) 

foo :: Foo Int 
foo = 0 

bar :: Foo Int 
bar = foo * 120 

दूसरे, आप coerce उपयोग कर सकते हैं आम तौर पर newtype कफन के बीच परिवर्तित करने के लिए:

import Data.Coerce 

newtype Foo a = Foo a 
newtype Bar a = Bar a 

a :: [(Foo (Bar Int), Foo())] 
a = [(Foo (Bar 0), Foo())] 

b :: [(Int,())] 
b = coerce a 

तीसरा, आप lens से iso -s उपयोग कर सकते हैं संक्षेप में नए प्रकार के रचनाकारों के ऊपर/नीचे संचालन को स्थानांतरित करने के लिए।

{-# LANGUAGE TemplateHaskell #-} 

import Data.Set (Set) 
import qualified Data.Set as Set 
import Control.Lens 

newtype GraphEdge a = GraphEdge (Set a) 
makePrisms ''GraphEdge 

modifyItemsSomehow :: Ord a => GraphEdge a -> GraphEdge a 
modifyItemsSomehow = _GraphEdge %~ Set.map someFunction 
+0

'लेंस' अब ऑफर करता है (केवल 7.10+ के लिए; पता नहीं क्यों 7.8 नहीं - मेरी गलती हो सकती है) 'coerced :: forall s t a b। (Coercible एस ए, Coercible टी बी) => आईएसओ टी टी बी '। – dfeuer

+0

'लेंस' एक नए प्रकार के तहत एक ऑपरेशन करने के विभिन्न रूपों के लिए 'Control.Lens.Wrapped' मॉड्यूल भी प्रदान करता है। – Carl

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