1

I have this piece of code now:

 results
 |> List.filter(Belt.Option.isSome)
 |> List.map(item =>
      switch (item) {
      | Some(item) => item
      }
    )

Can anyone make it shorter? It is a filter that removes the non-valid values followed by a map that converts/unwraps the optional values to just values.

In Scala it would just be flatten:

scala> List(Some("test"),None,None,Some("foo"),Some("bar"),None).flatten
res4: List[String] = List(test, foo, bar)
glennsl
  • 28,186
  • 12
  • 57
  • 75
FelixHJ
  • 1,071
  • 3
  • 12
  • 26
  • 1
    As formulated, this question is more appropriate on [codereview.se]. You should ask specific questions on SO. I'll try to just answer how to flatten a `list` of `option`s instead. – glennsl Apr 15 '19 at 06:36
  • 1
    I took a surgical knife to your question to get to the meat of it. Hope that's okay. I think it's a great question formulated this way. – glennsl Apr 15 '19 at 06:57
  • thanks, yes definetely better this way – FelixHJ Apr 16 '19 at 07:24

1 Answers1

2

flatten in Scala seems to work on any kind of monad. And this kind of polymorphism, called ad-hoc polymorphism, unfortunately isn't supported in OCaml (although it's on the roadmap, asa feature called "modular implicits"). Therefore we have to write code specific for lists of options. Using just Belt, we can do this:

[Some("test"), None, None, Some("foo"), Some("bar"), None]
|> Belt.List.keepMap(_, x => x)

keepMap is what is called filterMap in saner standard libraries, and takes a function that should return an option instead of a bool where a None will be filtered out and Some(x) will be flattened and included in the final list as just x.

glennsl
  • 28,186
  • 12
  • 57
  • 75
  • 3
    Just a quick note that (although Glenn is not a fan) the Belt library is designed to work well with the pipe-first operator, so that could also be `[...]->Belt.List.keepMap(x => x)`. – Yawar Apr 15 '19 at 11:10
  • 1
    Indeed :) The reason-specific version of the pipe-first operator is especially bad because the operator precedence is different, which can lead to surprising errors if you mix it with the ordinary pipe operator. – glennsl Apr 15 '19 at 15:54
  • great, thanks. Added a variant to play with here: https://reasonml.github.io/en/try?rrjsx=false&reason=DYUwLgBAhhC8EG0DKB7AtiAFAIjCAzmNgJQA0EAcigHYjlW3moY4BmKKJT6W2ARlABOXSjRABdANwAoUJD5xoEAD4A+CACEQwMADoAMgEtCugNYgQABwCyUS5gD65AB5x1z4jOkApfLuAoAOaYUJ4+fgHBfGFAA – FelixHJ Apr 16 '19 at 10:08