0

I'm a Haskell beginner and while building a simple project I came across this odd problem.

I have a list of functions e.g.

[f1, f2, f3 ... fn] 

Which doesn't work because they don't have same type. Some have Ct -> String, Ct -> Double and Ct -> Maybe Double

What I wanted to do was apply the functions applicatively like this

[f1, f2, f3 ... fn] <*> [v1, v2, v3 ... vn] 

where all vs have same type Ct

The problem can be easily solved by just using list comprehension with tuples like

[(f1 a, f2 a, f3 a ... fn a) | a <- [v1, v2, v3 ... vn]]

which would look something like this

[ (f1 v1, f2 v1, f3 v1, f4, v1 ... fn v1)

, (f2 v1, f2 v2, f3 v2, f4 v2 ... fn v2)

, ...

, (fn v1, fn v2, fn v3, fn v4 ... fn vn)

]

but n is quite a large number where you have to define a separate instance of show to say print them on terminal, which is one of the thing I want to do.

I know a few ways of overcoming this problem, one is by using tuples but dividing results into smaller chunks but I was wondering, is there a way of defining a datatype that can encapsulate multiple datatypes and still retain 'idiomaticity' and readable code of applicative style?

atis
  • 881
  • 5
  • 22

1 Answers1

3

Make three lists, of types [Ct -> String], [Ct -> Double], and [Ct -> Maybe Double]. Each may be applied to your [Ct] applicatively.

Two alternative solutions come to mind and are immediately discarded: a fresh data type which can hold any of a String, a Double, or a Maybe Double; or existentials, which are essentially just a more uniform packaging of the same idea. Idea one would look like this:

data Weird
    = It'sAString String
    | It'sADouble Double
    | It'sAMaybe (Maybe Double)

You would then use e.g. [It'sAString . f1, It'sADouble . f2, It'sAMaybe . f3], which has type [Ct -> Weird] and can be used applicatively. To me this already seems like more machinery than it's worth, especially considering that your consumers must now be prepared to handle any of these three constructors.

The existential way would be even worse: you'd want to identify (or create) a class which covers all the things you could want to do with a String, a Double, or a Maybe Double, and which sensibly unifies all three types, first. Ouch. There's waaay too much stuff you could want to do for that to make sense.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • Wouldn't the final list have different types anyways? Or did you mean apply to `[Ct]` separately? Along with printing them I also want to use `sortBy (comparing someFunction)` on the final result. Would that mean I'll have to take the complicated path you mentioned in your 3rd and 4th para? – atis Nov 29 '18 at 15:37
  • @atis What is "the final list" you refer to? You absolutely do *not* have to take any complicated path; you can and should take the path described in the first paragraph. I included the other two only for completeness and somewhat under duress. – Daniel Wagner Nov 29 '18 at 16:02
  • My thought processes was to have a list of tuples like the one in the question with all values of all sorts of types and sort the list of tuples by each tuple's second and third value, which would be `Double`. That's why I think I need the outputs connected somehow! The `String` is sort of a name for the whole tuple of data. – atis Nov 29 '18 at 16:11
  • By final list I mean the result of `[doubleF1, doubleF2] <*> [stringF1, stringF2] <*> [v1, v2 .. vn]` – atis Nov 29 '18 at 16:17
  • @atis I think you have tried to abstract your question away from the details so that it is of more general interest, which is admirable, but the abstraction is leaking. Make your question concrete enough that it shows what you actually need. – Daniel Wagner Nov 29 '18 at 16:28
  • Alright, I'll try to work it on my own and if I'm still struggling I'll make a new question thread. Thanks for the help! – atis Nov 29 '18 at 16:42