더 큰 그림을 얻기 위해 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 줄에서 작성된 것입니까? 나는 예에 기대어 있지만 내 추측은 희미합니다.

다음은 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]

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


7
이 질문을 읽는 것이 드문 즐거움이라고 말하고 싶습니다. "이 코드는 어떻게 작동합니까?" 질문을 자주하지만 질문이 무엇을하고 있고 아직 이해하지 못하는지에 대한이 수준의 설명은 거의 없습니다. 그것은 당신이 가진 격차에 대해 좋은 목표 답변을 작성하는 것을 정말로 재미있게 만듭니다.
Daniel Wagner

다니엘 감사합니다! 이 문제에 많은 시간을 보냈기 때문에 도움이 필요한 부분을 찾아 낼 수있었습니다.
Shreeman Gautam

@WillNess 답변도 효과가 있다고 덧붙이고 싶습니다. 눈에 더 쉽고 이해하기 쉽습니다.
Shreeman Gautam

답변:


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..] 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]있다 [].


당신은 당신의 투표 남자를 얻었다. 감사!
Shreeman Gautam

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 튜플 (지금의 두 번째 요소 걸릴 것입니다 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].


1
이봐 윌렘, 정말 좋은 설명이야! 나는 지금 전체 코드를 이해했다. 감사합니다!
Shreeman Gautam
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.