一般的なユーティリティ関数を使用してこれを行う方法を学ぶことをお勧めします。ここで必要な2つの主要な機能:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
。連想リスト(マップまたは辞書を表すために使用されるペアのリスト)でマッピングを検索します。
concatMap :: (a -> [b]) -> [a] -> [b]
。これはに似てmap
いますが、リストにマップされた関数はリストを返し、結果は連結されます(concatMap = concat . map
)。
使用するには、タイプを次のより一般的な同義語lookup
に変更する必要があります。Rule
type Rule = (Char, String)
String
これはの同義語であることも忘れないでください[Char]
。これはconcatMap
、に適用するとString
、各文字が文字列に置き換えられることを意味します。これで、例を次のように書くことができます(引数の順序を変更しました)。
apply :: [Rule] -> String -> String
apply rules = concatMap (applyChar rules)
-- | Apply the first matching rule to the character.
applyChar :: [Rule] -> Char -> String
applyChar rules c = case lookup c rules of
Nothing -> [c]
Just str -> str
-- EXAMPLE
rules = [ ('X', "HYHY")
, ('Y', "OO") ]
example = apply rules "XYF" -- evaluates to "HYHYOOF"
引数の型が結果と同じである場合、その引数を最後の引数にすることが役立つことが多いため、引数の順序を変更しましたapply
(関数のチェーンが容易になります)。
モジュール(= 、= )の効用関数fromMaybe :: a -> Maybe a -> a
を使用して、さらに進んでこれをワンライナーに変えることができます。Data.Maybe
fromMaybe default Nothing
default
fromMaybe default (Just x)
x
import Data.Maybe
apply rules = concatMap (\c -> fromMaybe [c] $ lookup c rules)
これを補完するために実行できる演習は、これらすべてのユーティリティ関数のバージョンを自分で手動で作成することです。lookup
、 (およびconcatMap
に分解します)、および。そうすれば、このソリューションに含まれる「フルスタック」を理解できます。concat :: [[a]] -> [a]
map :: (a -> b) -> [a] -> [b]
fromMaybe