Является ли JavaScript `then` таким же, как Haskell` fmap`? - PullRequest
0 голосов
/ 20 ноября 2018

В JavaScript у Promises есть метод с именем then, который используется для распаковки результата в случае успеха, например,

fetch("google.com").then(console.log)

Из этого урока на Haskell я также нашел похожую вещь, которая называется fmap, например,

fmap putStrLn (fetch "google.com")

Они выглядят довольно похоже, но я не уверен, что они эквивалентны . Вот почему я хотел спросить, являются ли они одним и тем же.

PS: термин эквивалент должен соответствовать термину эквивалента соответствия Карри-Ховарда.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Игнорируя классы типов, у нас есть следующие типы в 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

Так что в одном смысле они эквивалентны, а в другом нет. Например, предположим, что в Haskell существует тип обещания P, и мы хотим прочитать 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.

0 голосов
/ 20 ноября 2018

Они связаны, да.Но then для Promise s делает несколько разных вещей, которые в Haskell будут отдельными функциями, не все из класса Functor (тот, который обеспечивает fmap).

В Haskell Promise будет конструктором типа, параметризованным типом того, что он в конечном итоге возвращает, например Promise Int или Promise String.

Мы можем сделать этот тип экземпляром Functor, даваянас fmap :: (a -> b) -> Promise a -> Promise b.Это позволит нам отобразить вычисление pure на результат, в конечном итоге возвращаемый обещанием.Но это не позволило бы нам связать обещания!Если мы попробуем fmapping с функцией, которая возвращает обещание, скажем, типа Int -> Promise String, мы получим Promise, который вернул еще один Promise в конце, но не выполнил его, а это не то, что мы обычно хотим.

Мы также можем сделать Promise экземпляром Monad.Monad является подклассом Functor.Все Monad с Functor с, но не все Functor с Monad с.Monad даст нам функцию >>= (обычно называемую "bind"), которая будет иметь тип (>>=) :: Promise a -> (a -> Promise b) -> Promise b.Это было бы аналогично then, в котором обратный вызов возвращает другой Promise, который упорядочен после исходного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...