searchコマンドをByteStringで書き直すと上手く動かない・・・

countコマンドのRuby版アルゴリズムにHaskell/Pythonも合わせてみた+メモ化に関する疑問 - しんちゃんの日記で頂いたツムジさんのByteStringを使うと速くなるというアドバイスを元に、こちらのベンチマークのコードPython vs Ruby vs Haskell(文字列検索deベンチマーク) - しんちゃんの日記もByteStringに書き換えてみたんですが…

コード

import System.Environment
import qualified Data.ByteString.Char8 as B

search _ _ empty = []
search (y,x) s ns | B.take (B.length s) ns == s = (y,x):search (y,x + 1) s (B.tail ns)
search (y,_) s ns | B.head ns == '\n' = search (y + 1,1) s (B.tail ns)
search (y,x) s ns  = search (y,x + 1) s (B.tail ns)

main = getArgs >>= \args ->
		B.readFile (args!!0) >>=
		return.search (1,1) (B.pack (args!!1)) >>= \pos ->
		putStrLn (args!!0) >>
		print pos

何故か、空リストしか返さなくなっちゃいました…orz
search関数のパターンマッチにも問題があるみたいで、

search3.hs:4:1:
    Warning: Pattern match(es) are overlapped
             In an equation for `search':
                 search (y, _) s ns = ...
                 search (y, x) s ns = ...
                 search (y, x) s ns = ...
Linking search3.exe ...

と言う警告が出ます…

何で動かないんだろう?謎だ…


2013年2月19日追記

tanakhさんのアドバイスのお蔭で動くようになりました!!

動くようになったコードはこちら!

import System.Environment
import qualified Data.ByteString.Char8 as B

search _ _ ns | B.null ns = []
search (y,x) s ns | B.take (B.length s) ns == s = (y,x):search (y,x + 1) s (B.tail ns)
search (y,_) s ns | B.head ns == '\n' = search (y + 1,1) s (B.tail ns)
search (y,x) s ns  = search (y,x + 1) s (B.tail ns)

main = getArgs >>= \args ->
		B.readFile (args!!0) >>=
		return.search (1,1) (B.pack (args!!1)) >>= \pos ->
		putStrLn (args!!0) >>
		print pos

私の環境では

>difftime search pi.dat 7777777
pi.dat
[(298906,35),(517833,1),(517833,2),(517833,3)]


1.4843963s

Python/Rubyに勝てないとコメントで書きましたが、オリジナルの方が、改めてベンチ取り直してみたら4秒とかなり遅かったので、現在の環境で今夜にでもまたベンチ取り直してみます。



2013年2月20日追記

Python vs Ruby vs Haskell(文字列検索deベンチマーク) - しんちゃんの日記をベンチ取り直して更新しましたが、Haskellが両言語に肉薄はするものの、順位は変わりませんでした…orz
通りすがりさんのコードをByteStringに直さないと勝てないかも知れません…