直接ではありません。問題は、文字が多型のための機能を持たないビルトイン型であることです。これは、Num
タイプのクラスを使用して多型になるように設計された数値リテラルとは異なります。
つまり、スマートコンストラクタを持つ新しいタイプのラッパー、まったく新しいタイプの2つの基本的なアプローチがあります。
の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
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
ここで、newtypeは非初期化入力とサニタイズ入力を区別します。 CleanString
を作成する唯一の方法がcleanString
である場合、CleanString
がすべて適切に消毒されていることが静的にわかります(cleanString
が正しい場合)。あなたのケースでは、実際には母音ではなく、子音のためのタイプが必要なようです。
HaskellのNewtypeは非常に軽量ですが、プログラマはラッピングとアンラッピングを行うコードを記述して使用する必要があります。多くの場合、その利点は余分な作業を上回ります。しかし、私は本当にあなたのString
が母音でないことを知っていることを知っておくことが重要なアプリケーションについては考えていないので、おそらく普通のString
で作業しています。
* newtypesはコンパイル時にのみ存在するため、理論的にはnewtypesは実行時のパフォーマンスコストがありません。しかし、その存在は、生成されたコードを変更することがあり(例えば、ルールを抑制する)、測定可能なパフォーマンスの影響があることがあります。
私は母音がUNIX名に許されなかったことに気づいていなかった;) –
は、なぜあなたは「母音のデータ型」をしたいですか?それは何をするでしょうか? –
@Anschel、おそらく 'Char'であり、その値は母音だけを取ることができます。これは 'unixname'の正当性基準の一つを宣言する方法です。実際に彼は補完が必要だからではありませんが、あなたはそのアイデアを得ます。 – luqui