You're looking for the First
Monoid
instance for Maybe
. Used like—
import Data.Foldable (foldMap)
import Data.Monoid (First(..))
fractionParse :: String -> FractionParse
fractionParse s = fromMaybe Rubbish . getFirst
$ foldMap First [ maybeFraction s
, maybeWhole s
]
It doesn't make sense to encode your own failure values in your datatypes, so I'd remove the Rubbish
Constructor.
data FractionParse = Fraction Int Int | Whole Int
deriving (Show, Eq)
fractionParse :: String -> Maybe FractionParse
Use Control.Monad.guard
instead of manually sending up your own sentinel values (as in maybeNumDenom
).
maybeNumDenom s = do
guard $ containsExactlyOneSlash s
-- ...
Take advantage of incremental parsing to implement maybeNumDenom
, then you won't have to do so much extraneous filtering, counting, and finger crossing. And by removing the Rubbish
constructor, at the point you have a correct parse you know you can return a Fraction
, so—
import Data.Maybe (listToMaybe)
maybeFraction :: String -> Maybe FractionParse
maybeFraction s = listToMaybe $ do
(n, '/':s') <- reads s
(d, ''"") <- reads s'
return (Fraction n d)
The above function operates in the list monad. listToMaybe
converts a list to a Maybe
value by returning Just
the first element of the list, or Nothing
in the case of an empty list. reads :: Read a => String -> [(a, String)]
produces possible parses from a given string, returning the remainder of the unparsed string as the second element of each tuple. Binding to (d, ''"")
ensures that only parses that consume the whole string will be returned.
You're looking for the First
Monoid
instance for Maybe
. Used like—
import Data.Foldable (foldMap)
import Data.Monoid (First(..))
fractionParse :: String -> FractionParse
fractionParse s = fromMaybe Rubbish . getFirst
$ foldMap First [ maybeFraction s
, maybeWhole s
]
It doesn't make sense to encode your own failure values in your datatypes, so I'd remove the Rubbish
Constructor.
data FractionParse = Fraction Int Int | Whole Int
deriving (Show, Eq)
fractionParse :: String -> Maybe FractionParse
Use Control.Monad.guard
instead of manually sending up your own sentinel values (as in maybeNumDenom
).
maybeNumDenom s = do
guard $ containsExactlyOneSlash s
-- ...
Take advantage of incremental parsing to implement maybeNumDenom
, then you won't have to do so much extraneous filtering, counting, and finger crossing. And by removing the Rubbish
constructor, at the point you have a correct parse you know you can return a Fraction
, so—
import Data.Maybe (listToMaybe)
maybeFraction :: String -> Maybe FractionParse
maybeFraction s = listToMaybe $ do
(n, '/':s') <- reads s
(d, '') <- reads s'
return (Fraction n d)
The above function operates in the list monad. listToMaybe
converts a list to a Maybe
value by returning Just
the first element of the list, or Nothing
in the case of an empty list. reads :: Read a => String -> [(a, String)]
produces possible parses from a given string, returning the remainder of the unparsed string as the second element of each tuple. Binding to (d, '')
ensures that only parses that consume the whole string will be returned.
You're looking for the First
Monoid
instance for Maybe
. Used like—
import Data.Foldable (foldMap)
import Data.Monoid (First(..))
fractionParse :: String -> FractionParse
fractionParse s = fromMaybe Rubbish . getFirst
$ foldMap First [ maybeFraction s
, maybeWhole s
]
It doesn't make sense to encode your own failure values in your datatypes, so I'd remove the Rubbish
Constructor.
data FractionParse = Fraction Int Int | Whole Int
deriving (Show, Eq)
fractionParse :: String -> Maybe FractionParse
Use Control.Monad.guard
instead of manually sending up your own sentinel values (as in maybeNumDenom
).
maybeNumDenom s = do
guard $ containsExactlyOneSlash s
-- ...
Take advantage of incremental parsing to implement maybeNumDenom
, then you won't have to do so much extraneous filtering, counting, and finger crossing. And by removing the Rubbish
constructor, at the point you have a correct parse you know you can return a Fraction
, so—
import Data.Maybe (listToMaybe)
maybeFraction :: String -> Maybe FractionParse
maybeFraction s = listToMaybe $ do
(n, '/':s') <- reads s
(d, "") <- reads s'
return (Fraction n d)
The above function operates in the list monad. listToMaybe
converts a list to a Maybe
value by returning Just
the first element of the list, or Nothing
in the case of an empty list. reads :: Read a => String -> [(a, String)]
produces possible parses from a given string, returning the remainder of the unparsed string as the second element of each tuple. Binding to (d, "")
ensures that only parses that consume the whole string will be returned.
You're looking for the First
Monoid
instance for Maybe
. Used like—
import Data.Foldable (foldMap)
import Data.Monoid (First(..))
fractionParse :: String -> FractionParse
fractionParse s = fromMaybe Rubbish . getFirst
$ foldMap First [ maybeFraction s
, maybeWhole s
]
It doesn't make sense to encode your own failure values in your datatypes, so I'd remove the Rubbish
Constructor.
data FractionParse = Fraction Int Int | Whole Int
deriving (Show, Eq)
fractionParse :: String -> Maybe FractionParse
Use Control.Monad.guard
instead of manually sending up your own sentinel values (as in maybeNumDenom
).
maybeNumDenom s = do
guard $ containsExactlyOneSlash s
-- ...
Take advantage of incremental parsing to implement maybeNumDenom
, then you won't have to do so much extraneous filtering, counting, and finger crossing. And by removing the Rubbish
constructor, at the point you have a correct parse you know you can return a Fraction
, so—
import Data.Maybe (listToMaybe)
maybeFraction :: String -> Maybe FractionParse
maybeFraction s = listToMaybe $ do
(n, '/':s') <- reads s
(d, '') <- reads s'
return (Fraction n d)
The above function operates in the list monad. listToMaybe
converts a list to a Maybe
value by returning Just
the first element of the list, or Nothing
in the case of an empty list. reads :: Read a => String -> [(a, String)]
produces possible parses from a given string, returning the remainder of the unparsed string as the second element of each tuple. Binding to (d, '')
ensures that only parses that consume the whole string will be returned.