@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"

И почему порядок именно такой, как вы определили?
  • Вопрос задан
  • 205 просмотров
Решения вопроса 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 создали, который, когда его дёрнут, начнёт что-то там вычислять. В этом примере, когда дёрнут, начнёт вычислять, а не фейлится ли парсер, для чего придётся убедиться, что не фейлятся входящие в него парсеры. Порядок может быть любой, но автор библиотеки скорее всего сделал порядок естественным.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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