Аппликативный функтор в списках

Я понимаю, что будет следующее:

[(+2),(+1)]<*>[1,2,3] == [3,4,5,2,3,4]

Я также понимаю, что fmap реализован как map. Но как я мог мысленно отобразить это вычисление в своей голове? Когда я впервые увидел это, я предположил следующее:

[(*2),(+1)]<*>[1,2,3] == [4,5,6]

Второй раз я подумал о: [[3,4,5],[2,3,4]]. Но, с другой стороны, <*> возвращает f b, поэтому я знал, что это невозможно. Итак, мой вопрос: какие шаги в уме, чтобы понять это?


person Rui Peres    schedule 17.12.2014    source источник


Ответы (3)


fs <*> xs более или менее [f x | f <- fs, x <- xs]. У монад есть аппликативный экземпляр

fM <*> xM = do 
  f <- fM
  x <- xM
  return (f x)

что довольно точно соответствует пониманию списка.

person Louis Wasserman    schedule 17.12.2014

Чтобы запомнить это, вам может быть проще просто представить <*> как × (декартово произведение):

[a, b, c] × [x, y, z] == [a x, a y, a z, b x, b y, ...]
person Shoe    schedule 17.12.2014
comment
Фактически, (,) <$> xs <*> ys создает представление xs × ys. - person dfeuer; 06.01.2015

Интересно. Всегда ли аппликатив должен быть декартовым произведением? Или стратегия действительно вопрос выбора? Например, может ли быть действительным "почтовый индекс" из двух списков? то есть:

[F1,F2,F3] <*> [a,b,c] == [F1 a, F2 b, F3 c]

person Sri    schedule 03.11.2018
comment
Это могло бы. Это реализовано в Control.Applicative.ZipList. - person Alistair Wall; 05.04.2020