जिस तरह से "एनीमिक मॉडल" समस्या का वर्णन किया गया है वह एफपी के लिए अच्छी तरह से अनुवाद नहीं करता है। पहले इसे उपयुक्त रूप से सामान्यीकृत करने की आवश्यकता है। यह दिल में है, एक एनीमिक मॉडल एक मॉडल है जिसमें इस बारे में ज्ञान होता है कि इसे कैसे ठीक से उपयोग किया जाए जो मॉडल द्वारा खुद को समझाया नहीं गया है। इसके बजाय, यह ज्ञान संबंधित सेवाओं के ढेर के आसपास फैला हुआ है। उन सेवाओं को केवल मॉडल का ग्राहक होना चाहिए , लेकिन इसके एनीमिया के कारण उन्हें इसके लिए जिम्मेदार माना जाता है। उदाहरण के लिए, एक Account
वर्ग पर विचार करें जिसका उपयोग खातों को सक्रिय करने या निष्क्रिय करने या किसी खाते के बारे में जानकारी देखने के लिए नहीं किया जा सकता है जब तक कि एक AccountManager
वर्ग के माध्यम से नियंत्रित नहीं किया जाता है । खाते को मूल संचालन के लिए जिम्मेदार होना चाहिए, न कि कुछ बाहरी प्रबंधक वर्ग को।
कार्यात्मक प्रोग्रामिंग में, एक समान समस्या मौजूद होती है जब डेटा प्रकार सही रूप से प्रतिनिधित्व नहीं करते हैं कि वे मॉडल के लिए क्या कर रहे हैं। मान लें कि हमें उपयोगकर्ता आईडी का प्रतिनिधित्व करने वाले एक प्रकार को परिभाषित करने की आवश्यकता है। एक "एनीमिक" परिभाषा बताती है कि उपयोगकर्ता आईडी स्ट्रिंग हैं। यह तकनीकी रूप से संभव है, लेकिन बड़ी समस्याओं में चलता है क्योंकि उपयोगकर्ता आईडी का उपयोग मनमाने तारों की तरह नहीं किया जाता है। इसका कोई मतलब नहीं है कि उन्हें संक्षिप्त करें या उनमें से सबस्ट्रिंग को खत्म कर दें, यूनिकोड वास्तव में मायने नहीं रखता है, और उन्हें यूआरएल और अन्य संदर्भों में सख्त चरित्र और प्रारूप सीमाओं के साथ आसानी से एम्बेड किया जाना चाहिए।
इस समस्या का समाधान आमतौर पर कुछ चरणों में होता है। एक सरल पहली कटौती यह है कि "ठीक है, एक UserID
स्ट्रिंग के बराबर का प्रतिनिधित्व किया जाता है, लेकिन वे अलग-अलग प्रकार के होते हैं और आप एक का उपयोग नहीं कर सकते जहां आप दूसरे की अपेक्षा करते हैं।" हास्केल (और कुछ अन्य टाइप की गई कार्यात्मक भाषाएं) इस सुविधा को प्रदान करती हैं newtype
:
newtype UserID = UserID String
यह एक को परिभाषित करता है UserID
समारोह जो जब दिए गए एक String
कि है एक मूल्य के निर्माण की तरह व्यवहार एक UserID
प्रकार प्रणाली द्वारा, लेकिन जो अभी भी सिर्फ एक है String
रनटाइम पर। अब फ़ंक्शंस यह घोषित कर सकते हैं कि उन्हें UserID
एक स्ट्रिंग के बजाय आवश्यकता है ; UserID
एस का उपयोग करते हुए जहां आप पहले कोड को UserID
एक साथ दो एस के साथ तार गार्ड का उपयोग कर रहे थे । प्रकार प्रणाली की गारंटी है कि ऐसा नहीं हो सकता है, कोई परीक्षण की आवश्यकता नहीं है।
यहां कमजोरी यह है कि कोड अभी भी किसी भी String
तरह की मनमानी ले सकता है "hello"
और इससे निर्माण कर UserID
सकता है। आगे के चरणों में एक "स्मार्ट कंस्ट्रक्टर" फ़ंक्शन बनाना शामिल है, जब एक स्ट्रिंग कुछ इन्वर्टर की जांच करता है और केवल तभी वापस लौटता है UserID
जब वे संतुष्ट होते हैं। फिर "डंब" UserID
कंस्ट्रक्टर को निजी बनाया जाता है, इसलिए यदि कोई ग्राहक चाहता है तो UserID
उन्हें स्मार्ट कंस्ट्रक्टर का उपयोग करना चाहिए , जिससे विकृत यूजरआईडी को अस्तित्व में आने से रोका जा सके।
इससे भी आगे के कदम UserID
डेटा प्रकार को इस तरह से परिभाषित करते हैं कि यह असंभव है कि "विकृत" या "अनुचित", बस परिभाषा से। उदाहरण के लिए, UserID
अंकों की सूची के रूप में परिभाषित करना :
data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine
data UserID = UserID [Digit]
निर्माण करने के लिए एक UserID
अंक की एक सूची प्रदान की जानी चाहिए। इस परिभाषा को देखते हुए, यह दिखाना तुच्छ UserID
है कि किसी URL में प्रतिनिधित्व नहीं किया जा सकता। हास्केल में इस तरह के डेटा मॉडल को परिभाषित करना अक्सर उन्नत प्रकार की प्रणाली सुविधाओं जैसे डेटा किंड्स और सामान्यीकृत बीजीय डेटा प्रकारों (जीएडीटी) द्वारा सहायता प्राप्त होता है , जो आपके कोड के बारे में और अधिक चालन को परिभाषित करने और साबित करने के लिए टाइप सिस्टम की अनुमति देता है। जब डेटा व्यवहार से हटा दिया जाता है तो आपकी डेटा परिभाषा ही एकमात्र तरीका है जिसे आपको व्यवहार को लागू करना होगा।