Расшифровать структуру дерева JSON

В библиотеке bs-json приведен пример преобразования структуры json в дерево с использованием andThen комбинатор. Оригинальный пример можно найти здесь на github в файле интерфейса ML. Копирование функции decodeTree из этого файла в браузер инструментов разума отображается синтаксическая ошибка.

Был бы очень признателен за любые указания для того, чтобы заставить это работать.

Моя попытка перевести его на Reason3 приводит к ошибке типа. Это код:

type tree('a) =
  | Node('a, list(tree('a)))
  | Leaf('a);

let json = {| {
  "type": "node",
  "value": 9
  "children": [{
    "type": "leaf",
    "value": 5,
    "children": [{
      "type": "leaf",
      "value": 3
    }, {
      "type": "leaf",
      "value": 2
    }]
  }, {
      "type": "leaf",
      "value": 4
  }]
} |};

let decodeTree = (decodeValue, json) =>
  Json.Decode.(
    field("type", string)
    |> andThen(type_ =>
         switch type_ {
         | "node" =>
           Node(
             field("value", decodeValue),
             field("children", children =>
               children |> array(decodeTree) |> map(Array.to_list)
             )
           )
         | "leaf" => Leaf(field("value", decodeValue))
         }
       )
  );

let myTree = json |> Json.parseOrRaise |> decodeTree(Json.Decode.int);

Это ошибка типа,

This has type:
   tree('a)
But somewhere wanted:
   Json.Decode.decoder('b) (defined as (Js.Json.t) => 'b)

1 ответ

Решение

Извини за это. Не совсем уверен, что происходит с этим примером. Вот тот, который должен работать:

/* Decode a JSON tree structure */
type tree('a) =
  | Node('a, list(tree('a)))
  | Leaf('a);

module Decode = {
  open Json.Decode;

  let rec tree = decoder =>
    field("type", string) |> andThen(
       fun | "node" => node(decoder)
           | "leaf" => leaf(decoder)
           | _      => failwith("unknown node type")
     )

  and node = (decoder, json) =>
    Node(
      json |> field("value", decoder),
      json |> field("children", array(tree(decoder)) |> map(Array.to_list))
    )

  and leaf = (decoder, json) =>
    Leaf(json |> field("value", decoder));
};

let json = {| {
  "type": "node",
  "value": 9,
  "children": [{
    "type": "node",
    "value": 5,
    "children": [{
      "type": "leaf",
      "value": 3
    }, {
      "type": "leaf",
      "value": 2
    }]
  }, {
      "type": "leaf",
      "value": 4
  }]
} |};

let myTree =
  json |> Json.parseOrRaise
       |> Decode.tree(Json.Decode.int);

Изменить: конкретная ошибка вызвана andThen ожидая декодера, но получая tree('a) (Node или же Leaf). Все, что нужно, чтобы превратить его в декодер, - это добавить аргумент json, который вы передадите полевым декодерам:

|> andThen((type_, json) =>
     switch type_ {
     | "node" =>
       Node(
         json |> field("value", decodeValue),
         json |> field("children", children =>
           children |> array(decodeTree) |> map(Array.to_list)
         )
       )
     | "leaf" => json |> Leaf(field("value", decodeValue))
     }
   )
Другие вопросы по тегам