2014-11-15 3 views
1

잘 알려진 이디엄인가요? this $ that $ otherThing,이 경우apply2ws 잘 알려진 하스켈 관용구?

applyTwice someFunction head tail $ this $ that $ otherThing 

목록을 반환하고, 나는 두 끝을 공급 한 후 그 목록의 머리와 꼬리를 모두 가지고 가고,하고 싶은 : 여기

applyTwice :: (a -> b -> c) -> (d -> a) -> (d -> b) -> (d -> c) 
applyTwice g f1 f2 p = g (f1 p) (f2 p) 

은 일반적인 사용의 someFunction.

applyTwice은 표준 관용구입니까, 아니면 복잡한 계산 결과의 머리와 꼬리를 모두 자연스럽게 가져갈 수 있습니까? 이 작업을 수행하는 표준 방법으로 where을 사용하고 있습니까?

+3

확실히 StackOverflow에 속해 있습니다. 이것이 하스켈의 이론에 관한 것이라면 화제가 될 수도 있지만 관용구와 사용법에 대해 묻는 것은 확실히 그렇습니다. – jmite

+0

'applyTwice g f1 f2 = (g.f1) <*> f2'. 그래서, 예, 아니오. combinatory logic과 lambda-calculus의 [** S ** 결합 자] (https://en.wikipedia.org/wiki/SKI_combinator_calculus)입니다. –

+0

관련된 하스켈 연결자는 Data.Function.on :''(g''f''xy = g (fx) (fy)''''그러나 그것은 "하나의 함수, 두 개의 인자"를 가지고 다른 방향으로 나아 간다. –

답변

4

그냥 liftM2이 아닌가요? .

+0

예, 그렇습니다. –

+0

완벽! 내 "d"가 특정 유형이 아니기 때문에 Hoogle이 서명을 찾지 못했습니다. 하지만 저는 너무 일반적이었습니다. "d"를 배열에 사용했다는 것을 깨달았어야했고, liftM2는 배열을 모덜드로 사용합니다. –

+1

@MarshallhandheldFlax 사실, 여기 liftM은 Monad 인스턴스 인'(->) r' 함수를 사용하고 있습니다. 배열 사용과 관련이 없으며 사용자가 제공 한 완전히 일반적인 유형에서 작동합니다. –

1

표준 라이브러리에는 해당 기능이없는 것으로 보이지만 함수가 유용하다고 보입니다.

나는 무거운 할 수있는 두 가지 기능을 추출하는 경향 것

: 하나의 단일 인수로 두 가지 기능을 적용하고, 다른 두 개의 인수에 함수를 적용 :

split :: (a -> b) -> (a -> c) -> a -> (b,c) 
split f g x = (f x, g x) 

tupled :: (a -> b -> c) -> ((a, b) -> c) 
tupled f (x, y) = f x y 

이제 applyTwice 기능 수를 이 두 '빌딩 블록'기능의 관점에서 기록 : 내 split 문제의 화살표가 함수 타입 (->)되는 (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')의 특별한 경우이다

applyTwice :: (a -> b -> c) -> (d -> a) -> (d -> b) -> (d -> c) 
applyTwice g f1 f2 = tupled g . split f1 f2 

참고. 그리고 내 tupled은 표준 서곡의 uncurry :: (a -> b -> c) -> (a, b) -> c과 동일합니다.

그래서 우리는 표준 라이브러리 함수의 관점에서 applyTwice을 작성할 수 있습니다 이야기의

applyTwice g f1 f2 = uncurry g . (f1 &&& f2) 

교훈은 다음과 같습니다 대부분의 다형성 higher-order 함수는 이미 작성되었습니다. 좀 더 전문적인 것을 필요로 할 때 보통 표준 라이브러리를 기반으로 구축 할 수 있습니다.

+1

또는'import Control.Monad (liftM2)'. –

+1

@AaditMShah 또는 이와 유사하게 'import Control.Applicative (liftA2)' – Cubic