Равенство объектов с GHC [дубликат]

Вы можете использовать эту пользовательскую библиотеку (написанную с помощью 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)
});
2
задан amalloy 4 January 2015 в 05:55
поделиться

4 ответа

Нет, такого не бывает. Единственный способ рассказать обособленные ценности - это их структура; не существует тождества , как объекты на некоторых языках. То есть вы не можете отличить эти два значения друг от друга: (Just 5, Just 5) ведет себя точно так же, как let x = Just 5 in (x, x). Аналогично, нет никакой разницы между «этим Node 1» и «некоторым другим Node 1»: они неразличимы.

Обычно «решение» этой проблемы состоит в том, чтобы думать о вашей проблеме в некоторых других так что больше не нужно различать, основываясь на идентичности (и обычно там фактически не нужно). Но, как упоминалось в комментариях, вы можете эмулировать «указатель» механика других языков самостоятельно, создавая отдельные теги какого-либо типа, например, увеличивая целые числа и присваивая их каждому объекту, чтобы вы могли отличить их друг от друга.

6
ответ дан amalloy 23 August 2018 в 20:08
поделиться

Кристофер Микински заметил , что вы действительно можете сделать что-то подобное с монадой ST, и вы можете сделать это с помощью IO. В частности, вы можете создать STRef или IORef, который является своего рода изменяемым полем. Коробку можно получить только с помощью действий IO или ST, если это необходимо, что обеспечивает чистое разделение между «чистым» и «нечистым» кодом. Эти ссылки имеют идентификатор-запрос, если два равны, говорит вам, являются ли они фактически одним и тем же полем, а не имеют ли они одинаковое содержимое. Но это не очень приятно, а не то, что вы, вероятно, сделаете без веской причины.

2
ответ дан Community 23 August 2018 в 20:08
поделиться

Как указывали другие, в 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] работали.

«Равенство объектов» больше похоже на концепцию с императивных языков программирования, который предполагает, что есть распределители, предлагающие «ссылки» или «указатели», чтобы мы могли говорить о «равенстве объектов». Мы должны имитировать этот распределитель, я думаю, что это то, что делает функциональное программирование немного неудобным для решения проблемы.

2
ответ дан Javran 23 August 2018 в 20:08
поделиться

Нет, потому что это сломает ссылочную прозрачность . Результаты вызова метода с одним и тем же вводом несколько раз должны быть неотличимы, и должно быть возможно его прозрачно заменить вызовом метода с этим вводом один раз, а затем повторно использовать результат. Однако вызов метода, который возвращает некоторую структуру несколько раз, может каждый раз создавать новую копию структуры - структуры с различной «личностью». Если бы вы могли как-то сказать, что у них разные идентификаторы, тогда это нарушает ссылочную прозрачность.

1
ответ дан newacct 23 August 2018 в 20:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: