admin管理员组文章数量:1126335
I am trying to write a simple executable code in OCaml below.
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
("/?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 )
But I keep seeing the below when I run 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
From other StackOverflow posts, it seems to be related to the different types being returned in the if/else
but I have made sure all of the if/else
are using printf
.
I would appreciate if anyone can let me know what else I'm doing wrong.
I am trying to write a simple executable code in OCaml below.
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 )
But I keep seeing the below when I run 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
From other StackOverflow posts, it seems to be related to the different types being returned in the if/else
but I have made sure all of the if/else
are using printf
.
I would appreciate if anyone can let me know what else I'm doing wrong.
Share Improve this question edited Jan 9 at 7:04 Chris 36.3k5 gold badges31 silver badges54 bronze badges asked Jan 9 at 5:49 VlamVlam 1,7881 gold badge9 silver badges20 bronze badges 1 |2 Answers
Reset to default 2I'd suspect this is due to >>=
, whose type in Lwt is
(>>=) : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t
On the left-hand side you're passing it the result of Client.get url
, so the right-hand side must be a function returning the same type. Likewise, Lwt.run
expects an Lwt.t
. (I'm not intimately familiar with all the libraries involved, but Client.io
presumably is a type synonym expanding to Lwt.t
here.)
The fix for this example should be to use >|=
instead of the second >>=
, whose type is
(>|=) : 'a Lwt.t -> ('a -> 'b) -> 'b Lwt.t
Andreas Rossberg has identified one issue, but you're also seeing some operator precedence issues.
This kind of thing:
printf "ERROR: " ^ error_message
And this:
printf "HTTP Code: " ^ Int.to_string code
Look really suspicious, since printf "HTTP code: "
evaluates to ()
with cannot be provided to ^
. It looks like you meant to write something like:
printf ("HTTP Code: " ^ Int.to_string code)
But you might as well leverage printf
to write the following, which is cleaner and has no operator precedence issues.
printf "HTTP Code: %d" code
Also beware opening several modules. If more than one defines the same operator or they redefine standard library operators you can end up with some unexpected behavior.
Aside from fully qualifying names, you can locally open modules, mitigating this issue. But since you've already used this once in your code, it seems you're aware of this option.
On a style note, I might just refactor this:
let error_message = json |> member "error" |> member "error_message" |> to_string in printf "ERROR: " ^ error_message
To:
json
|> member "error"
|> member "error_message"
|> to_string
|> printf "ERROR: %s"
Also opinion, but there is an opportunity to rework:
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 )
Using pattern-matching and conditional guards:
match code with
| 200 when member "usage_type" json <> `Null ->
json
|> member "usage_type"
|> to_string
|> printf "usage_type: %s\n"
| 200 ->
printf
"ERROR: The usage_type field requires a paid subscription to the \
Starter plan or higher."
| (400 | 401) when member "error" json <> `Null ->
json
|> member "error"
|> member "error_message"
|> to_string
|> printf "ERROR: %s"
| _ -> printf "HTTP Code: %d" code
本文标签: ocamlThis expression has type unit but an expression was expected of type 39a ClientioStack Overflow
版权声明:本文标题:ocaml - This expression has type unit but an expression was expected of type 'a Client.io - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736670591a1946898.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
==
vs.=
– Chris Commented Jan 9 at 6:13