1

I've got an array of strings, call it a, where each individual string represents a number. I also have a function f : int -> int -> int, which I want to use to "reduce a to a single number". I would like to write:

a |> Array.reduce (fun x y -> f (int32 x) (int32 y))

but this does not work, because the type of "reduce" forbids me from returning integers from f (since a is an array of strings)

Is there a functional way to make this work without having to return a string from f or casting the string array to an int array beforehand?

Stefan Perko
  • 113
  • 5

1 Answers1

6

using Array.reduce mapping first

If you don't want to adapt your f to handle strings, and you want to use Array.reduce then yeah I guess you should convert first (and to be honest: it seems easier than doing it manually with your wrapper-lambda) - so why not just use

a
|> Array.map int32
|> Array.reduce f

instead?

if you are concerned with the overhead of producing an intermediate Array you can always switch Array. with Seq. to to it lazily:

a |> Seq.map int32 |> Seq.reduce f

using Array.fold

aside from that you can always fold to your hearts desire:

a |> Array.fold (fun n s -> n + int32 s) 0

so you might call this more functional or not ;)

Random Dev
  • 51,810
  • 9
  • 92
  • 119
  • Yes, I didn't want to first convert the whole array. I didn't know the "fold" method could do that. Thanks for pointing that out. – Stefan Perko Sep 06 '15 at 09:51
  • 3
    `fold` can do *everything* (it's the fundamental operation on lists as it shadows the lists definition) – Random Dev Sep 06 '15 at 09:52
  • @Carsten Can you elaborate on what you mean by "as it shadows the lists definition"? – sebhofer Sep 07 '15 at 09:26
  • @sebhofer it's the [list's catamorphism](https://en.wikipedia.org/wiki/Catamorphism#List_fold) and in lambda-calculus you usually [introduce lists with their fold](https://stackoverflow.com/questions/9846368/operations-on-church-lists-in-haskell) - but this is just *smart-talk* for the simple observation that the fold `fold f i ls` (ok actually it's `List.foldBack`) leaves the structure of a list `ls = 1::2::3::[]` untouched and just replaces `[]` with `i` and `::` with `f` (as an bin. operator): `fold (+) 0 ls = 1+(2+(3+0))` – Random Dev Sep 07 '15 at 09:44
  • Thank you Carsten! I will need a bit to digest that (I'm new to functional programming)... – sebhofer Sep 07 '15 at 09:47
  • should be no big issue for you (with that background) - it's just [*abstract nonsense*](https://en.wikipedia.org/wiki/Abstract_nonsense) - it's only there so that we can seem to be *a bit smarter* ;) – Random Dev Sep 07 '15 at 09:51
  • One important caveat to 'reduce' - it will fail in cases where the input collection is empty. For this reason you should always either take steps to ensure the collection isn't empty, or use something like 'fold' instead. Unless you are strict about your TDD (and thus start writing tests with base cases like empty inputs) this issue can very easily bypass your testing and catch you out in live running. – Kit Sep 07 '15 at 13:10