Вы можете использовать эту пользовательскую библиотеку (написанную с помощью Promise) для выполнения удаленного вызова.
function $http(apiConfig) {
return new Promise(function (resolve, reject) {
var client = new XMLHttpRequest();
client.open(apiConfig.method, apiConfig.url);
client.send();
client.onload = function () {
if (this.status >= 200 && this.status < 300) {
// Performs the function "resolve" when this.status is equal to 2xx.
// Your logic here.
resolve(this.response);
}
else {
// Performs the function "reject" when this.status is different than 2xx.
reject(this.statusText);
}
};
client.onerror = function () {
reject(this.statusText);
};
});
}
Пример простого использования:
$http({
method: 'get',
url: 'google.com'
}).then(function(response) {
console.log(response);
}, function(error) {
console.log(error)
});
Нет, такого не бывает. Единственный способ рассказать обособленные ценности - это их структура; не существует тождества , как объекты на некоторых языках. То есть вы не можете отличить эти два значения друг от друга: (Just 5, Just 5)
ведет себя точно так же, как let x = Just 5 in (x, x)
. Аналогично, нет никакой разницы между «этим Node 1
» и «некоторым другим Node 1
»: они неразличимы.
Обычно «решение» этой проблемы состоит в том, чтобы думать о вашей проблеме в некоторых других так что больше не нужно различать, основываясь на идентичности (и обычно там фактически не нужно). Но, как упоминалось в комментариях, вы можете эмулировать «указатель» механика других языков самостоятельно, создавая отдельные теги какого-либо типа, например, увеличивая целые числа и присваивая их каждому объекту, чтобы вы могли отличить их друг от друга.
Кристофер Микински заметил , что вы действительно можете сделать что-то подобное с монадой ST
, и вы можете сделать это с помощью IO
. В частности, вы можете создать STRef
или IORef
, который является своего рода изменяемым полем. Коробку можно получить только с помощью действий IO
или ST
, если это необходимо, что обеспечивает чистое разделение между «чистым» и «нечистым» кодом. Эти ссылки имеют идентификатор-запрос, если два равны, говорит вам, являются ли они фактически одним и тем же полем, а не имеют ли они одинаковое содержимое. Но это не очень приятно, а не то, что вы, вероятно, сделаете без веской причины.
Как указывали другие, в Haskell каждое значение является неизменным и нет объекта. Чтобы указать уникальный узел, вам нужно либо его структурировать (например, первый узел в связанном списке, который содержит 1
), либо дать каждому узлу дополнительный тэг каким-либо образом (имитируя, что происходит в императивном мире), чтобы мы могут различать их.
Чтобы структурно отличить узел от других, нам в основном нужно знать местоположение этого узла, например застежка-молния , которая не только дает вам значение в точке, но также и ее «окрестности».
И более подробно о том, «чтобы каждый узел добавлял дополнительный тег»:
Прежде всего, вам нужно сделать каждое значение объектом, для которого требуется генерировать уникальные теги во время выполнения. Обычно это делается с помощью распределителя, простейший распределитель может просто сохранить целое число, bump его, когда нам нужно создать новый объект:
-- | bumps counter
genId :: (Monad m, Functor m, Enum e) => StateT e m e
genId = get <* modify succ
-- | given a value, initializes a new node value
newNode :: (Monad m, Functor m, Enum e) => a -> StateT e m (a,e)
newNode x = genId >>= return . (x,)
И если вы хотите сделать существующий связанный список, нам нужно пройти через него и дать каждому значению узла тег, чтобы сделать его объектом:
-- | tags the llnked list with an extra value
tagged :: (Traversable f, Enum e, Monad m, Functor m)
=> f a -> StateT e m (f (a,e))
tagged = traverse newNode
И вот полная демоверсия, это выглядит неудобно Maybe "a little"
:
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable, TupleSections #-}
import Control.Applicative
import Control.Monad.State hiding (mapM_)
import Data.Traversable
import Data.Foldable
import Prelude hiding (mapM_)
data LL a = Empty | Node a (LL a)
deriving (Show, Eq, Functor, Foldable, Traversable)
-- | bumps counter
genId :: (Monad m, Functor m, Enum e) => StateT e m e
genId = get <* modify succ
-- | given a value, initializes a new node value
newNode :: (Monad m, Functor m, Enum e) => a -> StateT e m (a,e)
newNode x = genId >>= return . (x,)
example :: LL Int
example = Node 1 (Node 2 (Node 3 (Node 1 Empty)))
-- | tags the llnked list with an extra value
tagged :: (Traversable f, Enum e, Monad m, Functor m)
=> f a -> StateT e m (f (a,e))
tagged = traverse newNode
insertAfter :: (a -> Bool) -> a -> LL a -> LL a
insertAfter cond e ll = case ll of
Empty -> Empty
Node v vs -> Node v (if cond v
then Node e vs
else insertAfter cond e vs)
demo :: StateT Int IO ()
demo = do
-- ll1 = Node (1,0) (Node (2,1) (Node (3,2) (Node (1,3) Empty)))
ll1 <- tagged example
nd <- newNode 10
let tagIs t = (== t) . snd
ll2 = insertAfter (tagIs 0) nd ll1
-- ll2 = Node (1,0) (Node (10,4) (Node (2,1) (Node (3,2) (Node (1,3) Empty))))
ll3 = insertAfter (tagIs 3) nd ll1
-- ll3 = Node (1,0) (Node (2,1) (Node (3,2) (Node (1,3) (Node (10,4) Empty))))
liftIO $ mapM_ print [ll1,ll2,ll3]
main :: IO ()
main = evalStateT demo (0 :: Int)
В этой демонстрации tagIs
по существу делает вещь «равенство объекта», потому что ее интересует только дополнительный тег, который мы добавили раньше. Обратите внимание на то, что я обманул, чтобы указать два узла со своими «значениями», являющимися 1
: один помечен 0
, а другой отмечен 3
. Перед запуском программы невозможно определить, каков будет фактический тег. (Точно так же, как жесткое кодирование значения указателя и надеемся, что это сработает). В более реалистичной настройке вам понадобится другая функция для сканирования через связанный список и получения списка тегов с определенным значением (в этом примере, если вы просматриваете связанный список, чтобы найти все узлы с «значением» 1
, с которым вы бы [0,3]
работали.
«Равенство объектов» больше похоже на концепцию с императивных языков программирования, который предполагает, что есть распределители, предлагающие «ссылки» или «указатели», чтобы мы могли говорить о «равенстве объектов». Мы должны имитировать этот распределитель, я думаю, что это то, что делает функциональное программирование немного неудобным для решения проблемы.
Нет, потому что это сломает ссылочную прозрачность . Результаты вызова метода с одним и тем же вводом несколько раз должны быть неотличимы, и должно быть возможно его прозрачно заменить вызовом метода с этим вводом один раз, а затем повторно использовать результат. Однако вызов метода, который возвращает некоторую структуру несколько раз, может каждый раз создавать новую копию структуры - структуры с различной «личностью». Если бы вы могли как-то сказать, что у них разные идентификаторы, тогда это нарушает ссылочную прозрачность.