user3389445
user3389445

Reputation:

Function that returns first digit from a String

I'm trying to write a function that returns the first digit in a String, and if there isn't one then the function should return 1.

Example:

firstNumber "Example456" should return 4 because that is the first digit in the String.

firstNumber "Example" should return 1 because there is no digit.

This is what I have so far:

firstNumber :: String -> Int
firstNumber = read . maximumBy (length) . map (isDigit)

Can anyone help me here?

Upvotes: 0

Views: 586

Answers (2)

bheklilr
bheklilr

Reputation: 54058

Returning 1 if no number is found isn't very good, what if the string contains the number 1 and that was the first one? Instead, you could use the Maybe data type that represents either a failed computation with Nothing or a valid return value with Just.

You could do something like

firstNumber :: String -> Maybe Int
firstNumber s = fmap digitToInt $ listToMaybe $ filter isDigit

But you'll need Data.Maybe imported to get listToMaybe. Then you can use it as

> firstNumber "example"
Nothing
> firstNumber "example456"
Just 4

If you did want to return 1 on a failed search then you could just do

firstNumberOr1 :: String -> Int
firstNumberOr1 = fromMaybe 1 . firstNumber

The fromMaybe function has the definition

fromMaybe :: a -> Maybe a -> a
fromMaybe default Nothing = default
fromMaybe default (Just a) = a

So fromMaybe 1 will return 1 when given Nothing, and just unwrap whatever value was in the Just if given that.

Upvotes: 5

thor
thor

Reputation: 22460

You can do:

headDef [] = 1
headDef (x:_) = read [x]
firstNumber = headDef. filter isDigit

s="Example456"

Output:

*Main> firstNumber s
4
*Main> firstNumber "ex"
1
*Main>  

The function headDef tries to retrieve the first element of a list and replace it with a default value if the list is empty. You can change the default value/type in headDef to something else if necessary.

Upvotes: 2

Related Questions