@samarkad33

Как порядок вычисления выражений в этом коде?

Есть такой код на Хаскелле:

instance FromJSON Movie where
    parseJSON (Object o) = do
        movieValue <- head <$> o .: "movies"
        Movie <$> movieValue .: "id" <*> movieValue .: "title"
    parseJSON _ = mzero


Вот в этой строчке

Movie <$> movieValue .: "id" <*> movieValue .: "title"


какой порядок вычисления выражений? Вообще не могу понять. И в этой тоже

head <$> o .: "movies"

И почему порядок именно такой, как вы определили?
  • Вопрос задан
  • 204 просмотра
Решения вопроса 1
movieValue .: "id" создает парсер, читающий id. Применённый к нему Movie <$> создаёт парсер, который к id применит конструктор Movie, в итоге результатом такого парсера будет функция от одного недостающего аргумента.
Также movieValue .: "title" создаёт парсер, читающий title.
Если б это были просто функция и значение, можно было бы одно к другому применить, в нашем случае используют <*>, который создаст парсер, комбинирующий оба переданных ему парсера, применяя результат одного к результату другого. При этом так как оба парсера независимы, можно их выполнять в любом порядке. Но в данном случае слева направо. Проверить можно так:
parseEither (\(Object v) -> (,) <$> v .: "a" <*> v .: "b") (object [])

Ответ:
Left "key \"a\" not present"
Если бы он сначала вычислял правый аргумент, ошибка была бы другая - не найден b.

А что вы имеете в виду под порядком вычисления?
head <$> o .: "movies"
Хаскель ленивый язык, пока не понадобится, не вычисляет. В этой строке вы, считай, thunk создали, который, когда его дёрнут, начнёт что-то там вычислять. В этом примере, когда дёрнут, начнёт вычислять, а не фейлится ли парсер, для чего придётся убедиться, что не фейлятся входящие в него парсеры. Порядок может быть любой, но автор библиотеки скорее всего сделал порядок естественным.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы