Работая с книгой Haskell, мой мозг ломается на следующем примере. Я действительно не знаю, что делает функция flip
в строке 21.
1 class Functor f where
2 fmap :: (a -> b) -> f a -> f b
3
4 class Functor f => Applicative f where
5 pure :: a -> f a
6 (<*>) :: f (a -> b) -> f a -> f b
7
8 class Applicative f => Monad f where
9 return :: a -> f a
10 (>>=) :: f a -> (a -> f b) -> f b
11
12 instance Functor ((->) r) where
13 fmap = (.)
14
15 instance Applicative ((->) r) where
16 pure = const
17 f <*> a = \r -> f r (a r)
18
19 instance Monad ((->) r ) where
20 return = pure
21 ra >>= arb = flip arb <*> ra
-- flip :: (a -> b -> c) -> b -> a -> c
-- ra >>= arb = flip arb <*> ra
Насколько я понимаю, flip принимает функцию, которая принимает два аргумента, затем два отдельных аргумента и возвращает значение. В примере с привязкой мы передаем arb
как (a -> b -> c)
, затем <*>
как b
в подписи флипа и, наконец, ra
как a
? Я не вижу этого.
Я попытался сделать типы более конкретными для моего реального примера, чтобы вы могли переписать <*>
как
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
и я могу сделать то же самое для привязки
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
так что даже такой болван, как я, может видеть, что если бы мы могли поменять местами <*>
, мы могли бы выстроиться в линию, как
(<???>) :: (r -> a) -> (r -> a -> b) -> (r -> b)
(>>=) :: (r -> a) -> (a -> r -> b) -> (r -> b)
но, глядя на вторые аргументы, первый хочет r
в качестве первого аргумента, а bind хочет a
Итак, каким-то образом flip
пример из книги делает это для нас, но я действительно не понимаю, как это сделать. Любая помощь будет принята с благодарностью.
Благодарю вас!
flip f = \arg1 arg2 -> f arg2 arg1
— это все, что нужно, чтобы превратитьa -> r -> b
вr -> a -> b
. В Haskell, где все функции являются одним аргументом для одного значения (а значение иногда является другой функцией), это также эквивалентноflip f arg1 arg2 = f arg2 arg1
. - person Ry-♦   schedule 22.01.2019