[haskell] 더 큰 그림을 얻기 위해 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))와 같은 것을 의미한다는 것을 알았습니다. 내 질문은 x가 zip 줄에서 작성된 것입니까? 나는 예에 기대어 있지만 내 추측은 희미합니다.

다음은 fst와 snd에 대한 나의 이해입니다. 알아

    fst(1,2) = 1 

    snd(1,2) = 2

이 두 명령은 코드에서 어떻게 의미가 있습니까?

필터에 대한 이해는 조건과 일치하는 항목 목록을 반환한다는 것입니다. 예를 들어

    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]

전체적으로 어떻게 작동합니까? 나는 지금까지 내가 아는 것에 포괄적 이었지만 조각을 합칠 수는 없다고 생각합니다. 아무도 나를 도울 수 있습니까?



답변

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..] xs그러한 pred 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]있다 [].


답변

나는 이것이 다음과 같은 것을 의미한다는 것을 알았다 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 튜플 (지금의 두 번째 요소 걸릴 것입니다 1, 2, 0, 등)을하고 있는지 확인 pred그쪽 요소에 대한 만족 여부입니다. 만족하면 요소를 유지하고 그렇지 않으면 해당 요소 (2- 튜플)가 필터링됩니다.

경우에 따라서 (== 0)는 IS predicate, 다음 filter (pred . snd) (zip [0..] xs)2 튜플이 포함됩니다 [(2, 0), (4, 0)].

그러나 이제 결과는 2- 튜플 목록입니다. 인덱스를 원한다면 어떻게 든 2 튜플 과이 2 튜플의 두 번째 요소를 제거해야합니다. 우리는 그것을 위해 사용 fst :: (a, b) -> a합니다 : 이것은 첫 번째 요소에 2- 튜플을 매핑합니다. 목록은 그래서 [(2, 0), (4, 0)], map fst [(2, 0), (4, 0)]돌아갑니다 [2, 4].


답변