No directamente. El problema es que los caracteres son un tipo incorporado sin posibilidad de polimorfismo. Esto es diferente de los literales numéricos, que están diseñados para ser polimórficos a través de la clase de tipo Num
.
Dicho esto, hay dos enfoques básicos que puede tomar: un contenedor de tipo nuevo con un constructor inteligente o un tipo totalmente nuevo.
La envoltura newtype es más fácil de usar:
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
Desde el constructor Vowel
no se exporta, nuevos Vowel
s sólo puede ser creado por la función vowel
, que sólo admite los caracteres que desee.
También podría hacer un nuevo tipo de esta manera:
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'
Esta segunda forma es bastante pesado, y por lo tanto es mucho más difícil de usar.
Así que así es como hacerlo. Aunque no estoy muy seguro de que quieras hacerlo. La expresión habitual es hacer tipos que representan sus datos, y específicamente no representan las vocales. Un patrón común sería algo como esto:
newtype CleanString = Cleaned { raw :: String }
-- user input needs to be sanitized
cleanString :: String -> CleanString
Aquí el newtype distingue entre la entrada unsanitized y desinfectados. Si la única forma de hacer un CleanString
es por cleanString
, entonces sabrá estáticamente que cada CleanString
está desinfectado correctamente (siempre que cleanString
sea correcto). En tu caso, parece que realmente necesitas un tipo de consonantes, no de vocales.
Los tipos nuevos en Haskell son muy livianos *, pero el programador tiene que escribir y usar el código para realizar la envoltura y el desenvolver. En muchos casos, los beneficios superan el trabajo adicional. Sin embargo, realmente no puedo pensar en ninguna aplicación en la que sea importante saber que tu String
está libre de vocales, así que probablemente solo trabaje con un String
simple.
* los tipos nuevos solo existen en tiempo de compilación, por lo que, en teoría, no existe un costo de rendimiento en tiempo de ejecución para su uso. Sin embargo, su existencia puede cambiar el código producido (por ejemplo, inhibir REGLAS), por lo que a veces hay un impacto medible en el rendimiento.
yo no era consciente de que las vocales no estaban permitidos en nombres UNIX;) –
¿Por qué quiere un "tipo de datos para vocal"? ¿Qué haría? –
@Anschel, presumiblemente ser un 'Char' cuyos valores solo pueden asumir las vocales. Sería una forma de declarar uno de los criterios de corrección para 'unixname'. Er ... en realidad no porque necesita su complemento, pero entiendes la idea. – luqui