Edited at

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 の実装を参考にしました。