2017-01-07 10 views
5

Traversable은 구조가 "경로"(목록에 해당 할 수 있음)가있는 컨테이너 클래스이며 구조를 해체하지 않고 수정할 수있는 요소입니다. 따라서traversable을 목록과 함께 압축하는 가장 일반적인 방법은 무엇입니까?

zipTrav :: Traversable t => t a -> [b] -> Maybe (t (a,b)) 
zipTrav = evalStateT . traverse zp 
where zp a = do 
      bs <- get 
      case bs of 
       [] -> lift Nothing 
       (b:bs') -> put bs' >> return (a,b) 

그러나 목록 상태 순회는 약간 해킹 된 것으로 보이며 가장 효율적인 방법은 아닙니다. 위의 작업이나 일반적인 작업을 수행하는 표준 함수가 있다고 가정 할 수 있지만 그것이 무엇인지 파악할 수는 없습니다.

답변

5

mapAccumL/mapAccumR? 효율성의 문제에

tzipWith :: Traversable t => (a -> b -> c) -> [a] -> t b -> Maybe (t c) 
tzipWith f xs = sequenceA . snd . mapAccumL pair xs 
    where pair [] y = ([], Nothing) 
      pair (x:xs) y = (xs, Just (f x y)) 

tzip :: Traversable t => [a] -> t b -> Maybe (t (a, b)) 
tzip = tzipWith (,) 

ghci> tzip [1..] [4,5,6] 
Just [(1,4),(2,5),(3,6)] 

ghci> tzip [1,2] [4,5,6] 
Nothing 

- under the hood mapAccum 기능 그래서 나는 정말했던 모든 고차 함수에서 코드의 필수적 부분을 캡처하고, 상태 모나드를 사용합니다. 나는이 코드가 당신보다 더 잘 수행 될 것이라고 기대하지 않습니다. 하지만 State 모나드 (또는 ST)보다 훨씬 잘 할 수 있다고 생각하지 않습니다. 단 Traversable t으로 주어집니다.

+0

@WillNess Nah, 통과가 끝나면 입력 목록에 남아있는 것이 있는지 여부 만 확인하면됩니다. 나는 코드를 업데이트 할 것이다 –

+0

@WillNess 나는 Traversable을 채우기에 충분한 항목이 목록에 없으면 질문자가 Nothing을 반환하기를 원한다고 생각한다. 이 아이디어는 입력 값을 'Traversable'모양으로 유지하면서 각각의 값을 짝짓기하여 –

+0

아입니다. 이것은 이전 버전이 실제로 정확하다는 것을 의미합니다. :) 이전 버전을 복원하고 명확한 예를 추가했습니다. 이렇게 돼서 미안하다. –