Number.fromString is surprising... What's a good alternative?

Hello!

See this REPL session below:

import Data.Number as Number
Number.fromString “1”
(Just 1.0)

Number.fromString “1wat”
(Just 1.0)

It’s rather unfortunate that this wart bubbles up from JavaScript. I suppose this is by design.

What’s a good alternative to validate numbers coming from strings?

Thanks :slight_smile:

2 Likes

I think the easiest option is to either use a Number parser from one of the parsing libraries, eg: Parsing.String.Basic - purescript-parsing - Pursuit, or use FFI to use the Number constructor: Number() constructor - JavaScript | MDN

1 Like

Thanks for the suggestion!

Using a library looks like the only viable solution.

The FFI option looks like a no-go, you gotta love javascript

> Number(" ")
0
> (new Number(" ")).toString()
'0'

maybe you can do some stupid trick like const parseNumber= (s) => Number.parseFloat(s) == s ? Number.parseFloat(s) : NaN instead? I certainly did not check all of the stupid conversions JS is doing but for the case here it seems to work.


EDIT: well damn … " 0" - next try

const parseNumber = (s) => Number.parseFloat(s).toString() === s ? Number.parseFloat(s) : NaN

You might be interested in Data.Formatting.Parser.Number.parseNumber:

> runParser "1" (parseNumber <* eof)
(Right 1.0)

> runParser "1wat" (parseNumber <* eof)
(Left (ParseError "Expected EOF" (Position { column: 2, index: 1, line: 1 })))
1 Like

Thank you for that useful snippet!

I struggled a bit to find the proper imports because my knowledge is very basic at the moment (and I haven’t learned about monadic parsers yet).

But I think I got it right here, for ref:

> import Parsing (Parser, runParser)              
> import Parsing.String (eof)
> import Data.Formatter.Parser.Number (parseNumber)
> import Control.Applicative ((<*))

> runParser "1" (parseNumber <* eof)
(Right 1.0)

> runParser "1wat" (parseNumber <* eof)
(Left (ParseError "Expected EOF" (Position { column: 2, index: 1, line: 1 })))
3 Likes