web-dev-qa-db-ja.com

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

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

_    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))のようなものであることを発見しました。私の質問は、xZip行から作成されたリストですか?私はイエスに傾いていますが、私の推測は薄っぺらです。

次に、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]_

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

12
Shreeman Gautam

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]

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

こうやって。


list comprehensionsを使用すると、関数は次のように記述されます

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

これは、擬似コードでは次のようになります。

"結果リストには、(i,x)が保持するZip [0..] xs内の各pred xiが含まれます"

n-longを回してこれを行います

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

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

ここで、[a | True][a]で、[a | False][]です。

2
Will Ness