Estou tentando escrever um código executável simples em OCaml abaixo.
open Printf
open Lwt
open Cohttp
open Cohttp_lwt_unix
open Yojson
let () =
let ip = "8.8.8.8" in
let key = "" in
let uri =
Uri.of_string
("https://api.ip2location.io/?format=json&key=" ^ key ^ "&ip=" ^ ip)
in
Lwt_main.run
( Client.get uri >>= fun (resp, body) ->
let code = resp |> Response.status |> Code.code_of_status in
let json_promise = body |> Cohttp_lwt.Body.to_string in
json_promise >>= fun json_string ->
let json = Basic.from_string json_string in
let open Yojson.Basic.Util in
if code == 200 then
if member "usage_type" json <> `Null then
let usage_type = json |> member "usage_type" |> to_string in
printf "usage_type: %s\n" usage_type
else
printf
"ERROR: The usage_type field requires a paid subscription to the \
Starter plan or higher."
else if (code == 400 || code == 401) && member "error" json <> `Null then
let error_message =
json |> member "error" |> member "error_message" |> to_string
in
printf "ERROR: " ^ error_message
else printf "HTTP Code: " ^ Int.to_string code )
Mas continuo vendo o seguinte quando executo dune build
.
File "bin/main.ml", line 24, characters 10-46:
24 | printf "usage_type: %s\n" usage_type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type unit but an expression was expected of type
'a Client.io
Em outras postagens do StackOverflow, parece estar relacionado aos diferentes tipos retornados no , if/else
mas me certifiquei de que todos eles if/else
estão usando printf
.
Eu agradeceria se alguém pudesse me dizer o que mais estou fazendo errado.
Eu suspeito que isso se deva a
>>=
, cujo tipo em Lwt éNo lado esquerdo, você está passando o resultado de
Client.get url
, então o lado direito deve ser uma função retornando o mesmo tipo. Da mesma forma,Lwt.run
espera umLwt.t
. (Não estou intimamente familiarizado com todas as bibliotecas envolvidas, masClient.io
presumivelmente é um sinônimo de tipo expandindo paraLwt.t
aqui.)A correção para este exemplo deve ser usar
>|=
em vez do segundo>>=
, cujo tipo éAndreas Rossberg identificou um problema, mas você também está vendo alguns problemas de precedência de operadores .
Esse tipo de coisa:
E isto:
Parece realmente suspeito, já que
printf "HTTP code: "
avalia para()
with não pode ser fornecido para^
. Parece que você quis escrever algo como:Mas você também pode aproveitar
printf
para escrever o seguinte, que é mais limpo e não tem problemas de precedência de operadores.Também tenha cuidado ao abrir vários módulos. Se mais de um definir o mesmo operador ou redefinir operadores de biblioteca padrão, você pode acabar com algum comportamento inesperado.
Além de nomes totalmente qualificados, você pode abrir módulos localmente , mitigando esse problema. Mas como você já usou isso uma vez no seu código, parece que você está ciente dessa opção.
Em termos de estilo, eu poderia refatorar isso:
Para:
Também opinião, mas há uma oportunidade de retrabalho:
Usando correspondência de padrões e proteções condicionais: