巨大なcase-blockと小さなベンチマークを書く小さなHaskellスクリプトを書くのは難しくありません。たとえば:Test1.hs
とTest2.hs
:あなたはこのコードを実行した場合
module Main (main) where
mapping = zip ['!'..'z'] (reverse ['!'..'z'])
test_code =
[
"module Main where",
"",
"tester :: String -> String",
"tester cs = do",
" c <- cs",
" case transform c of",
" Just c' -> [c']",
" Nothing -> [c ]",
"",
"input = concat [ [' '..'z'] | x <- [1..10000] ]",
"",
"main = print $ length $ tester $ input",
""
]
code1 =
test_code ++
[
"transform :: Char -> Maybe Char",
"transform c = lookup c " ++ show mapping
]
code2 =
test_code ++
[
"transform :: Char -> Maybe Char",
"transform c =",
" case c of"
] ++
map (\(k, v) -> " " ++ show k ++ " -> Just " ++ show v) mapping ++
[
" _ -> Nothing"
]
main = do
writeFile "Test1.hs" (unlines code1)
writeFile "Test2.hs" (unlines code2)
、それは二つの小さなHaskellのソースファイルを生成します。前者は文字を文字にマップするのにPrelude.lookup
を使います。後者は巨大なケースブロックを使用します。両方のファイルには、大量のデータリストにマッピングを適用し、結果のサイズをプリントするコードが含まれています。 (この方法はI/Oを避け、他の点では支配的な要因になります。)私のシステムでは、Test1
は数秒で実行されますが、Test2
はほとんど瞬間です。
これ以上の読者の方は、Data.Map.lookup
を使用して速度を比較してみてください。
これは、パターン照合が、キー/値マッピングのリストのO(n)トラバースよりもはるかに高速であることを証明しています。しかし、あなた自身のベンチマークを作り上げてください。ネストされたケースとフラットケースの自動生成を試み、その結果をタイミングさせることができます。私の推測は、あなたに大きな違いは見られないが、それを試してみてくださいということです。
関連[* Haskell GHC:N個のコンストラクタとのパターン一致の時間複雑度は何ですか?](http://stackoverflow.com/q/9027384/2751851) – duplode