Не напрямую. Проблема в том, что символы являются встроенным типом без возможности полиморфизма. Это отличается от числовых литералов, которые разработаны как полиморфные с помощью класса Num
.
Тем не менее, есть два основных подхода, которые вы можете выбрать: обертка нового типа с умным конструктором или совершенно новый тип.
Обертка нового типа проще в использовании:
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
s могут быть созданы только функцией 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
Здесь новый тип различает необработанный и очищенный ввод. Если единственный способ сделать CleanString
- это cleanString
, то вы статически знаете, что каждый CleanString
должным образом очищен (при условии, что cleanString
является правильным). В вашем случае кажется, что вам действительно нужен тип для согласных, а не гласных.
Новые типы в Haskell очень легковесны *, но программисту действительно приходится писать и использовать код для переноса и развертывания. Во многих случаях преимущества перевешивают дополнительную работу. Тем не менее, я не могу придумать ни одного приложения, в котором важно знать, что ваш String
не содержит гласных, поэтому я, вероятно, просто поработаю с простым String
.
* newtypes существуют только во время компиляции, поэтому теоретически нет затрат производительности при их использовании. Однако их существование может изменить созданный код (например, запретить ПРАВИЛА), поэтому иногда наблюдается ощутимое влияние на производительность.