2011-10-01 10 views
7

मैंने वाक्य से स्वर हटाने के लिए निम्न कोड लिखा है:हास्केल में स्वर डेटाटाइप, क्या यह संभव है?

 main = print $ unixname "The House" 

    vowel x = elem x "aeiouAEIOU" 

    unixname :: [Char] -> [Char] 
    unixname [] = [] 
    unixname (x:xs) | vowel x = unixname xs 
      | otherwise = x : unixname xs 

बस सोच रहा है कि स्वर के लिए डेटा प्रकार बनाना संभव है या नहीं? कंपाइलर मुझे डेटा प्रकार में वर्णों का उपयोग करने नहीं देगा।

+2

मुझे पता है कि स्वर यूनिक्स नाम में अनुमति नहीं थी नहीं था,) –

+0

क्यों आप "स्वर के लिए डेटा प्रकार" एक चाहते हैं? यह क्या करेगा –

+2

@ एन्सेल, संभवतः एक 'चार' हो जिसका मूल्य केवल स्वरों पर ही ले सकता है। यह 'यूनिक्सनाम' के लिए शुद्धता मानदंडों में से एक घोषित करने का एक तरीका होगा। एर ... वास्तव में नहीं क्योंकि उसे इसके पूरक की जरूरत है, लेकिन आपको विचार मिलता है। – luqui

उत्तर

15

सीधे नहीं। समस्या यह है कि पात्र एक अंतर्निहित प्रकार हैं जिसमें बहुरूपता के लिए कोई सुविधा नहीं है। यह संख्यात्मक अक्षरों से अलग है, जिन्हें Num प्रकार वर्ग के माध्यम से पॉलिमॉर्फिक होने के लिए डिज़ाइन किया गया है।

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

newtype आवरण का उपयोग करना आसान है:

module Vowel (Vowel, vowel, fromVowel) where 

newtype Vowel = Vowel Char 

vowel :: Char -> Maybe (Vowel) 
vowel x | x `elem` "aeiouAEIOU" = Just (Vowel x) 
     | otherwise = Nothing 

fromVowel :: Vowel -> Char 
fromVowel (Vowel x) = x 

के बाद से Vowel निर्माता निर्यात नहीं किया है, तो नई Vowel ही vowel समारोह है, जो केवल पात्रों आप चाहते मानते द्वारा बनाई जा सकती है।

तुम भी कर सकता है इस तरह एक नए प्रकार:

data Vowel = A | E | I | O | U | Aa | Ee | Ii | Oo | Uu 

fromChar :: Char -> Maybe Vowel 
fromChar 'a' = Just Aa 
fromChar 'A' = Just A 
-- etc. 

toChar :: Vowel -> Char 
toChar Aa = 'a' 
toChar A = 'A' 

यह दूसरा रास्ता बहुत हैवीवेट है, और इसलिए भी बहुत कुछ अजीब उपयोग करने के लिए है।

तो ऐसा करने का तरीका है। मुझे पूरा यकीन नहीं है कि आप हालांकि चाहते हैं। सामान्य मुहावरे उन प्रकारों को बनाना है जो आपके डेटा का प्रतिनिधित्व करते हैं, और आप विशेष रूप से स्वरों का प्रतिनिधित्व नहीं करते हैं।

newtype CleanString = Cleaned { raw :: String } 

-- user input needs to be sanitized 
cleanString :: String -> CleanString 

यहाँ newtype unsanitized और स्वच्छ इनपुट बीच अंतर: एक आम पैटर्न कुछ इस तरह होगा। यदि CleanString बनाने का एकमात्र तरीका cleanString है, तो आप स्थिर रूप से जानते हैं कि प्रत्येक CleanString ठीक से संचरित है (बशर्ते cleanString सही है)। आपके मामले में, ऐसा लगता है कि आपको वास्तव में व्यंजनों के लिए एक प्रकार की आवश्यकता है, स्वर नहीं।

हास्केल में न्यूटाइप बहुत हल्के हैं *, लेकिन प्रोग्रामर को रैपिंग और अनैपिंग करने के लिए कोड लिखना और उपयोग करना होगा। कई मामलों में लाभ अतिरिक्त काम से अधिक है। हालांकि, मैं वास्तव में किसी भी एप्लिकेशन के बारे में नहीं सोच सकता जहां यह जानना महत्वपूर्ण है कि आपका String स्वर-मुक्त है, इसलिए मैं शायद सादा String के साथ काम करता हूं।

* न्यूटाइप केवल संकलन-समय पर मौजूद हैं, इसलिए सिद्धांत में इनका उपयोग करने के लिए कोई रनटाइम प्रदर्शन लागत नहीं है। हालांकि, उनका अस्तित्व उत्पादित कोड को बदल सकता है (उदा। आरयूएलई को अवरुद्ध करना), इसलिए कभी-कभी एक मापनीय प्रदर्शन प्रभाव होता है।

8

आप phantom types का उपयोग अतिरिक्त जानकारी के साथ पात्रों टैग करने के लिए, क्रम में संकलन समय के दौरान प्रकार प्रणाली गारंटी नहीं कि आपके तार केवल होते हैं, उदाहरण के लिए, स्वर या गैर स्वरों के लिए बनाने के लिए कर सकता है।

यहाँ एक खिलौना उदाहरण है:

{-# LANGUAGE EmptyDataDecls #-} 

import Data.Maybe 

newtype TaggedChar a = TaggedChar { fromTaggedChar :: Char } 

data Vowel 
data NonVowel 

isVowel x = x `elem` "aeiouyAEIOUY" 

toVowel :: Char -> Maybe (TaggedChar Vowel) 
toVowel x 
    | isVowel x = Just $ TaggedChar x 
    | otherwise = Nothing 

toNonVowel :: Char -> Maybe (TaggedChar NonVowel) 
toNonVowel x 
    | isVowel x = Nothing 
    | otherwise = Just $ TaggedChar x 

unixname :: [Char] -> [TaggedChar NonVowel] 
unixname = mapMaybe toNonVowel

इस दृष्टिकोण का लाभ यह है कि आप अभी भी भी काम करता है कि सभी TaggedChars पर टैग की परवाह किए बिना काम लिख सकते हैं।उदाहरण के लिए:

toString :: [TaggedChar a] -> String 
toString = map fromTaggedChar
संबंधित मुद्दे