List Comprehension in Ocaml?

你离开我真会死。 提交于 2019-11-29 12:40:56

问题


It seems that Ocaml batteries have comprehension syntax: http://en.wikipedia.org/wiki/List_comprehension#OCaml

However, what module should I include to use this syntax? I already open Batteries, but it doesn't work. Or is there a more idiomatic way to do list comprehension? I can use List.map and BatList.remove_if to achieve similar results, but that is much less elegant.


回答1:


Currently there're two libraries in OCaml that provide list comprehension, one was formerly a part of OCaml Batteries, another is shipped with camlp4. Neither is widely used and I, personally, do no recommend you to use any.

For list comprehension to work, you need to change the syntax of the language. This can be done with preprocessing your program, written in an extended syntax, with a camlp4 preprocessor. Also, list comprehension is not a first class citizen in OCaml community, and it is not well supported by the modern toolkits. Although, you can still easily play with it in a toplevel, for that you need, to install the list comprehension package:

opam install pa_comprehension 

and load it into a toplevel, using the following directives:

# #use "topfind";;
# #camlp4o;;
# #require "pa_comprehension";;
# open Batteries;;
# [? 2 * x | x <- 0 -- max_int ; x * x > 3 ?];;

But again, my personal opinion that list comprehension is not the best way to structure your code.

Life without comprehension

The example, you provided, can be expressed using core_kernel Sequence module (an analog of the Batteries Enum)

let f n =
  Sequence.(range 0 n |>
            filter ~f:(fun x -> x * x > 3) |>
            map ~f:(fun x -> x * 2))

Hence a filter |> map is such a common idiom there exists a filter_map function:

let f n =
  Sequence.(range 0 n |>
            filter_map ~f:(fun x ->
                if x * x > 3 then Some (x * 2) else None))

You may notice, that this examples takes more code, than list comprehension. But as soon as your programs will start to mature from simple hello world applications with integers to something more sophisticated, you will agree that using explicit iterators is more readable and comprehensible.

Also, since libraries in Core are so consistent, you can use a simple List instead of Sequence just by substituting the latter by the former. But of course, List is eager, unlike the Sequence, so playing with max_int using lists is not a good idea.

Moreover, since all containers are monads, you can use monadic operators for mapping, like:

let odds n = List.(range 0 n >>| fun x -> x * 2 + 1)



回答2:


list comprehension is already included in standard ocaml

#require "camlp4.listcomprehension";;

[ x * x | x <- [ 1;2;3;4;5] ];;

- : int list = [1; 4; 9; 16; 25]


来源:https://stackoverflow.com/questions/27652428/list-comprehension-in-ocaml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!