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
and
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.