None of the other replies mentioned the printf trick. So there you go, if you really, really want a variadic function a-la Julia, you can use that.
That said, unless you’re making a highly specific EDSL, using data structures is generally a better approach, at least because it’s a lot easier to fold/traverse data structures.
In the specific example above you can, reasonably speaking, introduce a type class and implement newMeasurement
as a “method” of that type class, with one instance per operation arity, provided the computation is the same for all operations of the same arity.
That being said, as far as I can tell, you’re implementing a system for tracking measurement errors across computations. If you only intend to use standard math (i.e. methods in Floating
and superclasses) on Measurement
, simply directly implementing Num
, Fractional
and Floating
for the Measurement
type shouldn’t be out of the question.
Edit: in the interest of transparency, the initial version of this post contained the following passage:
Side note, unless you’re not showing something huge, you don’t need rank-2 polymorphism there.
sqrtDiff :: Floating a => (a -> a) -> a -> a -> a
newMeasurement :: Floating a => (a -> a) -> Measurement a -> Measurement a
Given your implementations, these types behave largely the same in the end, but are a lot easier on the eyes.
This would be correct, if not for ad
, which wants rank-2 polymorphism.