git.iko.soy/typeable/inflections-hs
on master help sign in
Introduce a more flexible error handling
commit2a2d02847e86a3a8633d85b34e15957c30dd870f authormrkkrp <markkarpov@opmbx.org> dateWed 21 Dec 2016, 15:54 (10 years ago) parent48e14a3
3 files changed+40−34
CHANGELOG.md+3−1 Text/Inflections.hs+32−28 test/Text/InflectionsSpec.hs+5−5
CHANGELOG.md+3−1
@@ -14,7 +14,9 @@
1414* Switched test suite to Hspec.
1515
1616* The `toUnderscore`, `toDashed`, and `toCamelCased` are not partial
17− anymore, now they operate in `MonadThrow`.
17+ anymore. They return parse error in `Left` just like parsing functions,
18+ but this result can be lifted into any instance of `MonadThrow` with
19+ `betterThrow` helper.
1820
1921* Improved documentation.
2022
Text/Inflections.hs+32−28
@@ -48,10 +48,9 @@
4848-- Right [Word "foo",Word "bar"]
4949--
5050-- We can chain together the tokenization of the input String and the
51−-- transformation to CamelCase by using 'Control.Monad.LiftM':
51+-- transformation to CamelCase by using 'fmap':
5252--
53−-- >>> import Control.Monad (liftM)
54−-- >>> liftM camelize $ parseSnakeCase "foo_bar"
53+-- >>> camelize <$> parseSnakeCase [] "foo_bar"
5554-- Right "FooBar"
5655--
5756-- By separating out the tokenization from the application of inflections,
@@ -110,10 +109,10 @@ module Text.Inflections
110109 -- * Often used combinators
111110 , toUnderscore
112111 , toDashed
113− , toCamelCased )
112+ , toCamelCased
113+ , betterThrow )
114114where
115115
116−import Control.Monad (liftM)
117116import Control.Monad.Catch (MonadThrow (..))
118117import Data.Text (Text)
119118import Text.Inflections.Camelize (camelize, camelizeCustom)
@@ -134,43 +133,48 @@ import Text.Megaparsec
134133import Prelude hiding (Word)
135134#endif
136135
137−-- | Transforms CamelCasedString to snake_cased_string_with_underscores. In
138−-- case of failed parsing 'InflectionException' is thrown.
136+-- | Transforms CamelCasedString to snake_cased_string_with_underscores.
137+--
138+-- > toUnderscore = fmap underscore . parseCamelCase []
139139--
140140-- >>> toUnderscore "FooBarBazz"
141141-- "foo_bar_bazz"
142−toUnderscore :: MonadThrow m => Text -> m Text
143−toUnderscore = liftM underscore . handleEither . parseCamelCase []
144−{-# INLINE toUnderscore #-}
142+toUnderscore :: Text -> Either (ParseError Char Dec) Text
143+toUnderscore = fmap underscore . parseCamelCase []
145144
146−-- | Transforms CamelCasedString to snake-cased-string-with-dashes. In case
147−-- of failed parsing 'InflectionException' is thrown.
145+-- | Transforms CamelCasedString to snake-cased-string-with-dashes.
146+--
147+-- > toDashed = fmap dasherize . parseCamelCase []
148148--
149149-- >>> toDashed "FooBarBazz"
150150-- "foo-bar-bazz"
151−toDashed :: MonadThrow m => Text -> m Text
152−toDashed = liftM dasherize . handleEither . parseCamelCase []
153−{-# INLINE toDashed #-}
151+toDashed :: Text -> Either (ParseError Char Dec) Text
152+toDashed = fmap dasherize . parseCamelCase []
154153
155154-- | Transforms underscored_text to CamelCasedText. If first argument is
156155-- 'True' then FirstCharacter in result string will be in upper case. If
157−-- 'False' then firstCharacter will be in lower case. In case of failed
158−-- parsing 'InflectionException' is thrown.
156+-- 'False' then firstCharacter will be in lower case.
157+--
158+-- > toCamelCased t = fmap (camelizeCustom t) . parseSnakeCase []
159159--
160160-- >>> toCamelCased True "foo_bar_bazz"
161161-- "FooBarBazz"
162162-- >>> toCamelCased False "foo_bar_bazz"
163163-- "fooBarBazz"
164−toCamelCased :: MonadThrow m
165− => Bool -- ^ Capitalize the first character
164+toCamelCased
165+ :: Bool -- ^ Capitalize the first character
166166 -> Text -- ^ Input
167− -> m Text -- ^ Ouput
168−toCamelCased t = liftM (camelizeCustom t) . handleEither . parseSnakeCase []
169−{-# INLINE toCamelCased #-}
167+ -> Either (ParseError Char Dec) Text -- ^ Ouput
168+toCamelCased t = fmap (camelizeCustom t) . parseSnakeCase []
169+
170+-- | Lift something of type @'Either' ('ParseError' 'Char' 'Dec') a@ to
171+-- an instance of 'MonadThrow'. Useful when you want to shortcut on parsing
172+-- failures and you're in an instance of 'MonadThrow'.
173+--
174+-- This throws 'InflectionParsingFailed' if given value is inside 'Left'.
175+--
176+-- /since 0.3.0.0/
170177
171−-- | Take an 'Either' that can contain a parser error and throw it if
172−-- necessary. If everything is OK, just return 'Right' value.
173−handleEither :: MonadThrow m => Either (ParseError Char Dec) a -> m a
174−handleEither (Left err) = throwM (InflectionParsingFailed err)
175−handleEither (Right x) = return x
176−{-# INLINE handleEither #-}
178+betterThrow :: MonadThrow m => Either (ParseError Char Dec) a -> m a
179+betterThrow (Left err) = throwM (InflectionParsingFailed err)
180+betterThrow (Right x) = return x
test/Text/InflectionsSpec.hs+5−5
@@ -9,16 +9,16 @@ spec :: Spec
99spec = do
1010 describe "toUnderscore" $ do
1111 it "converts camel case to snake case" $
12− toUnderscore "camelCasedText" `shouldReturn` "camel_cased_text"
12+ toUnderscore "camelCasedText" `shouldBe` Right "camel_cased_text"
1313 it "converts camel case to snake case with numbers" $
14− toUnderscore "ipv4Address" `shouldReturn` "ipv4_address"
14+ toUnderscore "ipv4Address" `shouldBe` Right "ipv4_address"
1515 describe "toDashed" $
1616 it "converts camel case to dashed" $
17− toDashed "camelCasedText" `shouldReturn` "camel-cased-text"
17+ toDashed "camelCasedText" `shouldBe` Right "camel-cased-text"
1818 describe "toCamelCased" $ do
1919 context "when the first argument is False" $
2020 it "converts snake case to camel case" $
21− toCamelCased False "underscored_text" `shouldReturn` "underscoredText"
21+ toCamelCased False "underscored_text" `shouldBe` Right "underscoredText"
2222 context "when the first argument is True" $
2323 it "converts snake case to camel case" $
24− toCamelCased True "underscored_text" `shouldReturn` "UnderscoredText"
24+ toCamelCased True "underscored_text" `shouldBe` Right "UnderscoredText"