2

Есть функция для Haskell в стандартной библиотеке, которая принимает три функции и возвращает функцию, которая применяет возвращаемые значения первых двух функций третьей функции, что-то вроде этого:Compose функции в другую функцию

compact :: (a -> b) -> (a -> c) -> (b -> c -> d) -> a -> d 
compact a b c = \x -> c (a x) (b x) 

Или это:

import Control.Arrow 
compact' :: (a -> b) -> (a -> c) -> (b -> c -> d) -> a -> d 
compact' a b c = uncurry c . (a &&& b) 

Так что:

compact (take 1) (drop 2) (++) [1,2,3,4] == [1,3,4] 
compact (+10) (*2) (<) 11 == True 
compact (+10) (*2) (<) 9 == False 
+0

, что также 'с. a <*> b'. –

ответ

5

Если вы переупорядочить подпись:

(b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d 

это эквивалентно liftM2, так как ((->) r) is an instance of Monad type class

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r 

и

\> liftM2 (++) (take 1) (drop 2) [1, 2, 3, 4] 
[1,3,4] 

аналогично, liftA2 из Control.Applicative:

liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c 

\> liftA2 (++) (take 1) (drop 2) [1, 2, 3, 4] 
[1,3,4] 
+0

или если вы хотите познакомиться с 'Applicative', вы можете использовать' <*> ', чтобы обобщить это на функции произвольной arity:' (++) <$> принять 1 <*> drop 2' то же самое, что 'liftA2 (++) (возьмите 1) (падение 2) '. – rampion

4

liftM2 из Control.Monad почти такой же, как ваш compact функции, только с аргументами в другом порядке.

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r

что в контексте такой же, как:

liftM2 :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d

Итак:

liftM2 (++) (take 1) (drop 2) [1,2,3,4] == [1,3,4] 
liftM2 (<) (+10) (*2) 11 == True 
liftM2 (<) (+10) (*2) 9 == False 
Смежные вопросы