0

Does it make sense to have such functions defined

let squash12 (e:('a*('b*'c)   )) = e |> (fun (a,(b,c)  ) -> (a,b,c  ))
let squash21 (e:(('a*'b)*'c   )) = e |> (fun ((a,b),c  ) -> (a,b,c  ))
let squash13 (e:('a*('b*'c*'d))) = e |> (fun (a,(b,c,d)) -> (a,b,c,d))

let seqsquash12 (sa:seq<'T>) = sa |> Seq.map squash12
let seqsquash21 (sa:seq<'T>) = sa |> Seq.map squash21
let seqsquash13 (sa:seq<'T>) = sa |> Seq.map squash13

I could not find another way to make my core code recursive (leading to nested tuples), yet expose simple function that maps to generalized n-dimensional coordinates.

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
nicolas
  • 9,549
  • 3
  • 39
  • 83

2 Answers2

2

Yes, it makes sense to do so. The suggestion is avoiding lambda to make these functions easier to read:

let squash12 (a, (b, c)) = a, b, c

If you encounter inner tuples with varied arity very often, converting them into lists is not a bad idea. For example, e becomes a tuple of two lists:

(a, (b, c)) ~> ([a], [b; c])
(a, b), c) ~> ([a; b], [c])
(a, (b, c, d)) ~> (a, [b; c; d])

And we only need one function for sequence:

let seqsquash sa = sa |> Seq.map (@)

The problem is you lose the control over size of input. Pattern matching on list could help:

let squash12 (xs, ys) = 
   match xs, ys with
   | [a], [b; c] -> xs, ys
   | _ -> failwith "Wrong input size"
pad
  • 41,040
  • 7
  • 92
  • 166
2

I would have marked your functions as inline so that they could just be

let inline squash1 (a,(b,c)) = (a,b,c)

Also, you don't need the lambdas (fun ...)

John Palmer
  • 25,356
  • 3
  • 48
  • 67
  • thks. I noticed type inference is slow (i use higher order stuff only for base functions), so I might as well specify the type if it speeds it up. – nicolas Mar 02 '12 at 10:17
  • @nicolas - really, I don't think type inferrence is slow + this version will be much faster at runtime (avoids a function call) – John Palmer Mar 02 '12 at 10:21
  • @nicolas: See my answer for a suggestion in generic cases. – pad Mar 02 '12 at 10:25