Haskell

Haskell に python の find みたいなのがない

はじめての Qiita 投稿

Haskell の find

Haskell にも Data.Listfind があるのだけど

find :: Foldable t => (a -> Bool) -> t a -> Maybe a

これじゃない。 python の heystack.find('needle') みたいなやつがほしい。

あるかないか

python の find にも使い方がいくつかあると思うが、 needle の有無だけを知りたいなら isInfixOf を使えば良い。

インデックス

Data.List に findIndex とか findIndices とかあるけど求めているものじゃない。

findIndex :: (a -> Bool) -> [a] -> Maybe Int
findIndices :: (a -> Bool) -> [a] -> [Int]

こうかな?

findPython.hs
import Data.Maybe
import Data.List

findPython :: (Eq a) => [a] -> [a] -> Int
findPython needle heystack =
  maybe (-1) fst $ 
  listToMaybe . filter (isPrefixOf needle . snd) $ zip [0 .. ] (tails heystack)

main :: IO ()
main = do
  print $ findPython "abc" "0123456789abcde"
  print $ findPython "xyz" "0123456789abcde"

結果

$ stack runghc findPython.hs
10
-1

インデックス自体は必要ない時

インデックスを見つけるのは目的ではなく、見つけたインデックスの場所に書いてあるものを利用したい、という場合が多いのでは。 needle のインデックスを探すとか、 Haskell っぽくない気がする。

上にも出てくるが、 tails を使うのが Haskell 的なのだろう。

findURL.hs
import Data.Maybe
import Data.List

-- | "https://" を探し、その後が URL であると認識して URL を返す関数
findURL :: String -> Maybe String
findURL s = listToMaybe . filter (isPrefixOf "https://") $ tails s

main :: IO ()
main = do
  print $ findURL "qawsedrfujikolphttps://qiita.com/"

結果

$ stack runghc test2.hs
Just "https://qiita.com/"

References

Data.List -- Hackage

isInfixOf の実装を参考にしました。