Haskellコードのフラグメントを組み合わせて全体像を把握する


12

これは私がどこかで見つけたコードですが、これがどのように機能するか知りたいです:

    findIndices :: (a -> Bool) -> [a] -> [Int]
    findIndices _ [] = []
    findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))

出力:findIndices (== 0) [1,2,0,3,0]==[2,4]、ここpred(==0)xs[1,2,0,3,0]

私の理解の一部を紹介します。

    (zip [0..] xs)

上記の行が行うことは、リスト内のすべてにインデックスを付けることです。上記の入力の場合、次のようになります[(0,1),(1,2),(2,0),(3,3),(4,0)]

    (pred . snd)

これはのようなものであることがわかりましたpred (snd (x))。私の質問は、xリストはzip行から作成されていますか?私はイエスに傾いていますが、私の推測は薄っぺらです。

次は、私の理解であるfstsnd。そんなこと知ってる

    fst(1,2) = 1 

そして

    snd(1,2) = 2

これらの2つのコマンドはコードでどのように意味がありますか?

私の理解でfilterは、条件に一致するアイテムのリストを返します。例えば、

    listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]

与えるだろう [6,7,8,9,10]

マップについての私の理解は、リスト上のすべてのアイテムに関数を適用することです。例えば、

    times4 :: Int -> Int
    times4 x = x * 4
    listTimes4 = map times4 [1,2,3,4,5]

与えるだろう [4,8,12,16,20]

これは全体的にどのように機能しますか?私はこれまで私が知っていることで包括的であると思いますが、それらを完全にまとめることはできません。誰かが私を手伝ってくれる?


7
この質問を読んだことはまれな喜びでした。「このコードは一体どのように機能するのですか?」頻繁に質問しますが、質問者が何をして何を理解していないかのこのレベルの説明ではめったにありません。それはあなたが持っているギャップについて正確にターゲットを絞った答えを書くことを本当に楽しいものにします。
ダニエルワグナー

ダニエル、ありがとう!私はこの問題に多くの時間を費やしました。それが私が助けが必要なものを正確に示すことができた理由です。
シュリーマンゴータム

@WillNessの回答も機能することを付け加えたいと思います。目にやさしく、理解しやすいです。
シュリーマンゴータム

回答:


2

Haskellでは、タイプ従います。実際、ピースはタイプから対応するタイプへのワイヤーのように接続します。

(最初に、関数構成は次のとおりです:

   (f >>> g) x  =  (g . f) x  =        g (f x)
   (f >>> g)    =  (g . f)    =  \x -> g (f x)

そして、関数合成の型推論ルールは次のとおりです。

    f        :: a -> b                   --      x  :: a
          g  ::      b -> c              --    f x  :: b
   -------------------------             -- g (f x) :: c
    f >>> g  :: a ->      c
    g  .  f  :: a ->      c

今、)

findIndices :: (b -> Bool) -> [b] -> [Int]
findIndices pred  = \xs -> map fst ( filter (pred . snd) ( zip [0..] xs ))
                  =        map fst . filter (pred . snd) . zip [0..]
                  =  zip [0..]  >>>  filter (snd >>> pred)  >>>  map fst
---------------------------------------------------------------------------
zip :: [a] ->          [b]        ->        [(a,  b)]
zip  [0..] ::          [b]        ->        [(Int,b)]
---------------------------------------------------------------------------
        snd           :: (a,b) -> b
                pred  ::          b -> Bool
       ------------------------------------
       (snd >>> pred) :: (a,b)      -> Bool
---------------------------------------------------------------------------
filter ::               (t          -> Bool) -> [t]   -> [t]
filter (snd >>> pred) ::                      [(a,b)] -> [(a,b)]
filter (snd >>> pred) ::                    [(Int,b)] -> [(Int,b)]
---------------------------------------------------------------------------
    fst ::                                   (a,   b) -> a
map     ::                                  (t        -> s) -> [t] -> [s]
map fst ::                                                 [(a,b)] -> [a]
map fst ::                                               [(Int,b)] -> [Int]

だから、全体的に、

zip  [0..] ::          [b]        ->        [(Int,b)]
filter (snd >>> pred) ::                    [(Int,b)] -> [(Int,b)]
map fst ::                                               [(Int,b)] -> [Int]
---------------------------------------------------------------------------
findIndices pred ::    [b] ->                                         [Int]

あなたは尋ねました、これらの部分はどのように一緒に合うのですか?

こうやって。


リスト内包、あなたの関数は次のように書かれています

findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]

擬似コードではこれを読み取ります:

「そのような結果リストにはi、それぞれ(i,x)が含まれる」zip [0..] xspred x

これを行うには、n-long

xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]

  [0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]

どこ[a | True][a][a | False]あります[]


8

これはのようなものであることがわかりましたpred (snd (x))。私の質問は、xはzipラインから作成されたリストですか?私はイエスに傾いていますが、私の推測は薄っぺらです。

まあpred . snd、意味\x -> pred (snd x)です。だから、これは基本的要素にマッピング機能構築xにはpred (snd x)

したがって、これは式が次のようになることを意味します。

filter (\x -> pred (snd x)) (zip [0..] xs)

xしたがって、ここでは、によって生成された2タプルがありzipます。だから、どうかを知るためには(0, 1)(1,2)(2, 0)、などの結果に保持され、snd xこれらの2つの要素(これの2番目の要素になります120、など)を、そしてかどうかを確認predthaの要素には満足したりされていません。それが満たされている場合は、要素を保持します。それ以外の場合は、その要素(2タプル)がフィルターで除外されます。

したがって、(== 0)predicateである場合filter (pred . snd) (zip [0..] xs)、2タプルが含まれます[(2, 0), (4, 0)]

しかし、結果は2タプルのリストになります。インデックスが必要な場合は、どうにかして2タプルと、これらの2タプルの2番目の要素を取り除く必要があります。そのために使用fst :: (a, b) -> aします。これは、最初の要素に2タプルをマッピングします。したがって、リストの[(2, 0), (4, 0)]場合map fst [(2, 0), (4, 0)]は、が返され[2, 4]ます。


1
ウィレムさん、なんて素晴らしい説明でしょう!私は完全なコードを理解しました。ありがとうございます!
シュリーマンゴータム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.