使用 Async 发出 GET 请求

Use Async to make an GET request

摘自 Real World OCaml 书的 chapter 18,我正在尝试分解给出的示例。

我的范围,只是进行 GET 调用并打印我们返回的 JSON 的内容。

这是我的代码(它应该是给定示例的子集)

(* libraries *)
open Core.Std
open Async.Std


(* Generate a DuckDuckGo search URI from a query string *)
let query_uri query =
  let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in
  Uri.add_query_param base_uri ("q", [query])


(* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *)
let get_definition_from_json json_string =
  match Yojson.Safe.from_string json_string with
  | `Assoc kv_list ->
    let find key =
      begin match List.Assoc.find kv_list key with
      | None | Some (`String "") -> None
      | Some s -> Some (Yojson.Safe.to_string s)
      end
    in
    begin match find "Abstract" with
    | Some _ as x -> x
    | None -> find "Definition"
    end
  | _ -> None


(* Execute the DuckDuckGo search *)
let get_definition word =
  print_endline ("get_definition word:" ^ word);

  Cohttp_async.Client.get (query_uri word)
  >>= fun (_, body) ->
    Pipe.to_list (Cohttp_async.Body.to_pipe body)
  >>| fun strings ->
    (word, get_definition_from_json (String.concat strings))


(* run *)
let () =
  get_definition "OCaml"
  >>= fun (word, def) -> 
    print_endline ("- word: " ^ word);
    (
      match def with
        | None -> print_endline "[EMPTY]"
        | Some str -> print_endline str
    )

我的问题是我在编译时遇到这个错误:

ocaml setup.ml -build
Finished, 0 targets (0 cached) in 00:00:00.
+ /Users/antouank/.opam/system/bin/ocamlfind ocamlc -c -g -annot -bin-annot -thread -package yojson -package threads -package textwrap -package re2 -package core -package cohttp.async -I src -o src/main.cmo src/main.ml
File "src/main.ml", line 48, characters 18-41:
Error: This expression has type unit but an expression was expected of type
     'a Async.Std.Deferred.t = 'a Async_kernel.Deferred0.t
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
E: Failure("Command ''/usr/local/bin/ocamlbuild' src/main.native -use-ocamlfind -tag debug' terminated with error code 10")
make: *** [build] Error 1

如何从 Deferred 中获取字符串,该错误的确切含义是什么? 在书中,这个例子是 运行 有一个奇怪的命令包装,所以我看不出如何把它拉出来。

你定义的问题 run 是匿名函数

fun (word, def) -> 
    print_endline ("- word: " ^ word);
    (
      match def with
        | None -> print_endline "[EMPTY]"
        | Some str -> print_endline str
    )

类型不正确,无法与一元运算符一起使用 >>=。它具有类型 string * string -> unit>>= 在这里期望类型为 string * string -> unit Deferred.t.

的函数

如果您在同一章中查看 回声服务器 的示例,它会建议采用以下方法:

let run () =
  get_definition "OCaml"
  >>= fun (word, def) -> 
    print_endline ("- word: " ^ word);
    (
      match def with
        | None -> print_endline "[EMPTY]"
        | Some str -> print_endline str
    );
    Deferred.return()

let () =
  ignore(run ());
  never_returns (Scheduler.go ())