Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter a Maybe value

I am trying to create a function that validates an input String -> Maybe Int. I check to see if the input string is a number then check if that number is in a range. So far I have

validateNumber :: String -> Maybe Int
validateNumber n  = go $ (readMaybe::String -> Maybe Int) n
  where
    go (Just a) = inRange a
    go Nothing  = Nothing

inRange :: Int -> Maybe Int
inRange n
  | n > 0     = Just n
  | otherwise = Nothing

This feels like poor code. How should this be written?

Also, if I am trying to loop a function if it returns Nothing, what is the best way to do so:

So to loop the main function, I am doing :

case v of
  Nothing -> main
  Just x  -> {do something}
like image 264
matt Avatar asked Jul 26 '17 13:07

matt


2 Answers

You can use mfilter to filter out-of-range values within a Maybe instead of explicitly matching:

import Control.Monad (mfilter)

validateNumber :: String -> Maybe Int
validateNumber = mfilter (> 0) . readMaybe
like image 115
Lee Avatar answered Oct 08 '22 07:10

Lee


How about this?

validateNumber :: String -> Maybe Int
validateNumber n = (readMaybe n) >>= inRange

Or even this:

validateNumber :: String -> Maybe Int
validateNumber str = do
  n <- readMaybe str
  if n < 0 then Nothing else return n

(Avoids needing a separate inRange function.)

like image 8
MathematicalOrchid Avatar answered Oct 08 '22 05:10

MathematicalOrchid