So, I'm working on a new generic CLI args parser (mostly for my own benefit, we'll see if I come up with something useful worth publishing).
Let's just say to start with that I have a function that has this signature: (ArgumentConfiguration<'a> -> string array -> 'a * string array - so in other words, I have a function that will extract out and give me the value of a particular configured argument, and the remaining elements of the string array. The generic type 'a is unbounded, so it could be int, float, Foo, whatever. There's a Parse function in the config type that returns whatever I need.
Ok cool. Next thing is to have a data structure the user can input that contains all of those parsers, and a function that will take that structure and return the same "shape" of structure but instead of ArgumentConfiguration<'a> it will just return 'a. Here's a more concrete example:
(* Input Type *)
type ArgumentInput = {
A: ArgumentConfiguration<float>
B: ArgumentConfiguration<int>
C: ArgumentConfiguration<boolean>
}
(* Expected return type that I don't want to specify - I want it inferred *)
type ParserResult = {
A: float
B: int
C: boolean
}
The key is this: I want this to be as strongly typed as possible, but obviously I have different types of different arguments all over the place.
I'm open to doing different structures too - perhaps a Map might work? even a Sequence? Collections seem like not the right answer though if I'm going to have a ArgumentConfiguration<float> next to an ArgumentConfiguration<int> etc.
So given all of this info, here are my questions:
- What kind of data structure would work well to store these data so that the data and type can be transformed in a function?
- How would the function signature work?
- Because I'm familiar with Typescript and the way it does things (though I want this in F#) the signature I imagine would be like
type ParserFn = (config: Record<string, ArgumentConfiguration<any>>) => (args: string[]) => Record<string, any>;except that nukes the types for each record entry (and I don't think there's a good workaround in Typescript for that either; just using TS since I know it better)
- Because I'm familiar with Typescript and the way it does things (though I want this in F#) the signature I imagine would be like
Being enthusiastic about advanced FP concepts but not necessarily the most experienced, I wonder if I've stumbled on a limitation of the F# type system (would a new custom Type Provider help me?), and whether a language like Haskell or even Idris might be required to fully express the logic I'm looking at writing.