2013-05-21 2 views
15

때때로 다른 접기 기능을 사용하여 튜플 목록을 하나의 튜플로 접기를 원할 때가 있습니다. 예를 들어, runState 결과 목록을 함께 묶어 어떤 의미에서 결합 된 상태와 결합 된 결과를 얻으려면 그것은 작동하지만 나는이 람다에 대한 불편,화살표를 사용하여 튜플 목록을 접을 때

wish :: (a -> a' -> a) -> (b -> b' -> b) -> (a,b) -> [(a', b')] -> (a,b) 
wish lfn rfn x xs = foldl (\(a,b) -> (lfn a) *** (rfn b)) x xs 

:

는 다음의 구현을 고려하십시오. lfn *** rfn 그 자체는 (a,b) -> (a -> a', b -> b') 유형을 가지고 있는데, 패턴 일치를 사용하지 않고도 튜플에 올바르게 적용 할 수있는 방법을 찾을 수 없습니다. 내가 누락 된 명확하고 우아한 방법이 있습니까? 그것은 (a,a') -> (a -> a, a' -> a') -> (a, a') 유형의 라이브러리 함수 일 수도 있고 전혀 다른 접근 방식 일 수도 있습니다.

+2

BiApplicative 클래스의 일종입니다. 아마도 어딘가에 hackage가있을 것입니다. 그러나 나는 그것을 다른 사람들에게 남겨 두어 어떤 것이 좋고 더 이상 사용되지 않을지를 설명 할 것입니다. – Carl

+0

http://squing.blogspot.com/2008/11/beautiful-folding.html 및 Hackage에 대한 인스턴스화, http://hackage.haskell.org/package/ZipFold –

답변

9

Control.Arrow은 높은 수준의 기능에는 별 관심이 없습니다. 실제로 원하는 것은 함수 foo :: (a -> a' -> a'') -> (b -> b' -> b'') -> (a,b) -> (a',b') -> (a'',b'')입니다.이 함수는 arity 2의 함수 인 (***)의 아날로그입니다. 패키지 함수의 Data.Biapplicative에는이 함수가 있습니다.이 함수는 좀 더 일반적인 서명 biliftA2 :: Biapplicative w => (a -> b -> c) -> (d -> e -> f) -> w a d -> w b e -> w c f입니다. 2 요소 튜플에 대한 Biapplicative 인스턴스가 있기 때문에 이것이 모두 필요합니다.

코드에서 볼 수있는 유일한 불만은 람다의 currying이 명확하지 않다는 것입니다. 좀 더 명확한 \(a,b) (a',b') -> (lfn a a', rfn b b')을 선호 할 것입니다.

편집 노트 : 나는 필요한 기능이 존재하지 않는다고 결론을했고, 그것을 정의하는 것을 제안; Carl의 의견에 자극을 받으면 Biapplicative (더 일반적인 유형의 서명이 Hoogle이 내 제안 된 서명 아래에서이를 찾지 못하도록 막았습니다)에서 해당 키워드를 발견했습니다.

+0

'\ (a를 사용하여 수동 튜플 분해 , b) (a ', b') -> ... 일종의 멋진 개념을 사용하여 모든 강력한 원 라이너를 쓰는 전체 목적을 거부합니다. Biapplicative를 참조 해 주셔서 감사합니다. –

+0

내 요점은였습니다 비록 Biapplicative의'(<<**>>)'당신이 적용 할 필요가 유형이 있는가'(LFN *** RFN가)', 화살표의 호출이 날 여기로 여길 것 같다. 하지만 그건 내 직관이다. 화살표 기반의 접근법은 정확하고 반드시 명확하지는 않습니다. 하지만 나는''(lfn \'biLiftA2 \'rfn)'을 명시 적 람다로 선호한다. – isturdy