I’m keen to understand how other people tackle this one, and if my solution contains any gotchas.
When entering numeric values in input boxes, the box needs a String, but the consuming function(s) needs an Int or a Float. So what to store in the model?
When the input must be an integer, converting to an integer and then returning it to the box as a string works fine. But when it’s a float, there’s a problem which prevents decimal input:
Input string String.toFloat 1 1 12 12 12. 12 12.3 123
This might not be a problem if the input string is ‘processed’ only when focus is lost, but it’s [nicer|better|sometimes-required] to process and consume input character-by-character.
Storing the value in the model as a String, and then converting to Float when needed, solves the problem. But we lose any benefit of type checking.
My first try at a solution was:
type NumericString = NumericString NumType String type NumType = Int | Float
So we store the String and record what it represents (Int or Float). A consuming function can then check
NumType to ensure that the input is of the correct type.
But this can’t be type-checked by the compiler.
However, this can:
type IntString = IntString String type FloatString = FloatString String
The immediate consuming functions would be those that convert these new types to numeric values:
intStringToInt IntString -> Maybe Int intStringToInt intString = let (IntString string) = intString in String.toInt string
floatStringToInt FloatString -> Maybe Float floatStringToInt floatString = let (FloatString string) = floatString in String.toFloat string
And, of course, the equivalent for extracting the string to go back in the text box.