ocaml - deoptionalize a list: is there a simpler way?

馋奶兔 提交于 2019-12-11 12:18:30

问题


I have written a function to deoptionalize an integer list and I would like to know if there is a better way to write it.

let deoptionalize (lst:'a option list) : 'a list =
    List.map ~f:(fun x -> match x with Some x -> x | None -> assert false)
                    (List.filter ~f:(fun x -> x <> None) lst)
;;

In the assignment I am currently working its using map and filter is a must.


回答1:


I suppose that a "hand-coded" solution (i.e. without map and filter) is easier to read, but if you really need to use them, here you go:

It seems that you are using the Core library. If so, I think your solution is not so bad, but can be written a bit more compact:

let deoptionalize lst = 
    List.filter ~f:(is_some) lst
    |> List.map ~f:(function | Some x -> x | None -> assert false)

If you don't mind warnings (which I discourage you to do), you can even leave out some more:

let deoptionalize lst = 
    List.filter ~f:(is_some) lst
    |> List.map ~f:(fun (Some x) -> x)

Actually, Core provides filter_map (thanks @Ramon Snir for the hint) which combines both, so you can use:

let deopt lst = 
    List.filter_map ~f:(fun x -> x) lst;;



回答2:


In your case, I prefer doing in this way:

let deoptionalize l =
  let rec deopt acc = function
    | [] -> List.rev acc
    | None::tl -> deopt acc tl
    | Some x::tl -> deopt (x::acc) tl
  in 
  deopt [] l

It is more clear and tail-recursive and performance is better




回答3:


Another solution,

let deoptionalize l = 
    List.concat  @@ List.map (function | None -> [] | Some x -> [x]) l


来源:https://stackoverflow.com/questions/21674947/ocaml-deoptionalize-a-list-is-there-a-simpler-way

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