В JavaScript у Promises есть метод then, который используется для распаковки результата в случае успеха, например,
fetch("google.com").then(console.info)
Из это руководство по Haskell я тоже нашел похожую вещь, которая называется fmap, например,
fmap putStrLn (fetch "google.com")
Они выглядят очень похоже, но я не уверен, что это эквивалент. Вот почему я хотел спросить, одно ли это.
PS: Термин эквивалент должен быть эквивалентом типа корреспонденции Карри-Ховарда.
@BhojendraRauniyar Что не так с этим вопросом? Нарушает ли это какое-либо руководство по установке вопросов StackOverflow?
Я не уверен, как это нарушает, но почти уверен, что это не подходит для SO. Но я просто предлагал вам не сравнивать один язык с другим. В противном случае вам будет намного труднее учиться.
Да, это так. Обратите внимание, что .then перегружен, поэтому в конечном итоге он играет роль как fmap, так и >>= (обещания образуют монаду - см. Async для аналога Haskell).
@DanielWagner Итак, стоит ли применять вашу мудрую тавтологию и к Переписка Карри-Ховарда?
@WongJiaHau Если вы можете определить свое использование «эквивалента» так же тщательно, как Карри и Ховард определили свое использование «эквивалента», я буду счастлив ответить на ваш вопрос.
Документация Bluebird затрагивает эту тему: bluebirdjs.com/docs/coming-from-other-languages.html#haskell
Ваш код Haskell выглядит неправильно - я уверен, что это должен быть fetch "google.com" >>= putStrLn
возможный дубликат Почему монады обещаний?
Нет, они не эквивалентны в смысле Карри-Ховарда: фактически, ни один из них не кажется даже хорошо сформированными терминами ни в комбинаторных типах, ни в интуиционистской импликационной логике.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Они связаны, да. Но then для Promises делает несколько разных вещей, которые в Haskell были бы отдельными функциями, а не все из класса Functor (того, который предоставляет fmap).
В Haskell Promise был бы конструктором типа, параметризованным типом того, что он в конечном итоге возвращает, например Promise Int или Promise String.
Мы могли бы сделать этот тип экземпляром Functor, дав нам fmap :: (a -> b) -> Promise a -> Promise b. Это позволило бы нам сопоставить вычисление чистый с результатом, в конечном итоге возвращаемым обещанием. Но это не позволило бы нам сковать обещания! Если мы попробуем fmapping с функцией, которая возвращает обещание, скажем, типа Int -> Promise String, мы получим Promise, который вернул еще один Promise в конце, но не выполнил его, а это не то, что мы обычно хотим.
Мы также могли бы сделать Promise экземпляром Monad. Monad является подклассом Functor. Все Monad являются Functor, но не все Functor являются Monad. Monad даст нам функцию >>= (обычно называемую «привязкой»), которая будет иметь тип (>>=) :: Promise a -> (a -> Promise b) -> Promise b. Это было бы аналогично then, в котором обратный вызов возвращает другой Promise, который упорядочен после исходного.
Я не знаком с JS then. Было бы справедливо сказать, что then выполняет fmap, а затем выполняет join, если результат все еще остается Promise? Таким образом, мы не можем построить значение типа Promise (Promise a), верно? (Хотя я думаю, что мы могли бы получить Promise (Identity (Promise a)), чтобы обмануть then и заставить join не использовать два Promise.)
@chi Да, вот как это работает promisesaplus.com/#point-45 Когда-то были споры о том, насколько "перегрузить" then: github.com/promises-aplus/promises-spec/issues/…github.com/promises-aplus/promises-spec/issues/…
Игнорируя классы типов, у нас есть следующие типы в Haskell (мы будем говорить, что наличие правильных классов типов Haskell соответствует наличию подходящего метода .then в JavaScript):
fmap :: (a -> b) -> f a -> f b
bind :: (a -> f b) -> f a -> f b
А в JavaScript у нас есть (придуманный синтаксис):
.then :: (this :: f a) -> (a -> (b || f b)) -> f b
Так что в одном смысле они эквивалентны, а в другом - нет. Например, предположим, что какой-то тип обещания называется P в Haskell, и мы хотим прочитать URL-адрес из файла, а затем дать обещание получить этот URL-адрес:
read :: String -> P String
fetch :: String -> P String
readFetch :: String -> P (P String)
readFetch file = fmap fetch (read file)
А потом вы можете do:
fetched <- readFetch someFile
...
foo <- fetched
В JavaScript, если вы сделали read(file).then(fetch), это было бы эквивалентно следующему Haskell:
readFetch :: String -> P String
readFetch file = bind fetch (read file)
Таким образом, первое выполняется только после чтения файла, а второе - после завершения выборки (т.е. позже).
Мы пришли к выводу, что then похож, но не совсем то же самое, что и fmap.
Если вы идете к новому учителю, то не напоминайте старого учителя.