Non direttamente. Il problema è che i caratteri sono un tipo built-in senza alcuna possibilità di polimorfismo. Questo è diverso dai letterali numerici, che sono progettati per essere polimorfici tramite la classe di tipo Num
.
Detto questo, ci sono due approcci di base che è possibile adottare: un wrapper newtype con un costruttore intelligente o un tipo completamente nuovo.
L'involucro Newtype è più facile da usare:
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
Poiché il costruttore Vowel
non viene esportata, nuove Vowel
s possono essere creati solo dalla funzione vowel
, che ammette solo i caratteri desiderati.
Si potrebbe anche fare un nuovo tipo come questo:
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'
Questo secondo modo è abbastanza pesante, e quindi è molto più scomodi da usare.
Ecco come si fa. Non sono abbastanza certo che tu voglia farlo. Il solito idioma è quello di creare tipi che rappresentano i tuoi dati, e in particolare lo non rappresenta rappresentare le vocali. Un modello comune sarebbe qualcosa di simile:
newtype CleanString = Cleaned { raw :: String }
-- user input needs to be sanitized
cleanString :: String -> CleanString
Qui il newtype distingue tra ingresso unsanitized e igienizzati. Se l'unico modo per fare un CleanString
è di cleanString
, allora sai staticamente che ogni CleanString
è correttamente disinfettato (a condizione che cleanString
sia corretto). Nel tuo caso, sembra che tu abbia effettivamente bisogno di un tipo per le consonanti, non per le vocali.
I nuovi tipi in Haskell sono molto leggeri *, ma il programmatore deve scrivere e utilizzare il codice per eseguire il wrapping e lo unwrapping. In molti casi i benefici superano il lavoro extra. Tuttavia, non riesco a pensare a nessuna applicazione in cui è importante sapere che il tuo String
è privo di vocale, quindi probabilmente lavorerei solo con un semplice String
.
* I newtypes esistono solo in fase di compilazione, quindi in teoria non ci sono costi di runtime per l'utilizzo. Tuttavia, la loro esistenza può cambiare il codice prodotto (ad esempio inibendo le RULE), quindi a volte c'è un impatto misurabile sulle prestazioni.
non ero consapevole del fatto che le vocali non sono stati ammessi nei nomi UNIX;) –
Perché vuoi un "tipo di dati per vocale"? Cosa farebbe? –
@Anschel, presumibilmente un 'Char' i cui valori possono solo assumere vocali. Sarebbe un modo per dichiarare uno dei criteri di correttezza per 'unixname'. Ehm ... in realtà non perché ha bisogno del suo complemento, ma tu hai l'idea. – luqui