2016-12-20 5 views
1

Я пытаюсь выяснить, с лямбда-исчисления, почему функция результат следующего кодаКак работает <*> с функцией Аппликация?

(,) <$> (+1) <*> (+1) 

имеет тип Num а => а -> (а, а) вместо Num а => а -> а -> (a, a)

Это то, что у меня есть, я делаю что-то ужасно неправильное или < *> просто подключен таким образом?

(\x, y -> (,) x y) <$> (\x -> x + 1) <*> (\x -> x + 1) 

-- fmap applies first 

(\x y -> (,) ((+1) x) y) <*> (\x -> x + 1) -- substituted the lambda with (+1) for better clarity 

-- then goes apply 

(\x y -> (,) ((+1) x) ((+1) y)) 

Как параметры лямбда объединяются и в какой точке?

+2

По определению, на это приложение, 'f <*> g = \ x -> fx (gx)'. Обратите внимание, что здесь, если 'f' является двоичным, результат является унарной функцией. Ваш последний результат должен быть '\ x -> (,) ((+1) x) ((+1) x)' – chi

ответ

4

Давайте посмотрим типы в вашем примере:

(,)   <$> (+1)   <*> (+1) 
^    ^    ^
|     |     | 
a -> b -> (a, b) Num a => a -> a  Num a => a -> a 

Rhs из (<$>) и Rhs/LHS из (<*>) должен быть Аппликативный Functor. Ваш функтор - Num a => (->) a (монад-ридер).

Итак, какой тип будет после (<$>) применения (псевдокод):

a -> b -> (a, b) <$> Num a => (->) a a ==> Num a => (->) a (b -> (a, b)) 

После (<*>) (псевдокод):

Num a => (->) a (b -> (a, b)) <*> Num a => (->) a a ==> Num a => (->) a (a, a) 

Num a => (->) a (a, a) Но это эквивалентно Num a => a -> (a, a).


Как @chi писал в голове, реализация (<*>) для типа (->) r является:

(<*>) :: (->) r (a -> b) -> (->) r a -> (->) r b 
f <*> g = \r -> f r (g r) 

И, если вы подаете заявление, вы получите:

(\x y -> (,) x y) <$> (\r -> r + 1) <*> (\r -> r + 1) = 
= (\r y -> (,) (r + 1) y) <*> (\r -> r + 1) = 
= \r -> (,) (r + 1) (r + 1) 
Смежные вопросы