Skip to content

Commit d6c02e2

Browse files
committed
Manual: 2x slower
1 parent 7bef629 commit d6c02e2

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

src/Data/Csv/Conversion.hs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,9 @@ class FromField a where
772772
genericParseField
773773
:: forall a rep meta. (Generic a, GFromField rep, Rep a ~ D1 meta rep, Datatype meta)
774774
=> Options -> Field -> Parser a
775-
genericParseField opts field = fmap (to . M1) (gParseField opts field)
776-
<|> fail ("Can't parseField for " <> datatypeName (Proxy :: Proxy meta d f))
775+
genericParseField opts field = fmap (to . M1) (gParseField opts onFail field)
776+
where
777+
onFail _ = fail $ "Can't parseField of type " <> datatypeName (Proxy :: Proxy meta d f)
777778
{-# INLINE genericParseField #-}
778779

779780
-- | A type that can be converted to a single CSV field.
@@ -1395,12 +1396,12 @@ instance (ToField a, Selector s) => GToRecord (M1 S s (K1 i a)) (B.ByteString, B
13951396
name = T.encodeUtf8 (T.pack (fieldLabelModifier opts (selName m)))
13961397

13971398
class GFromField f where
1398-
gParseField :: Options -> Field -> Parser (f p)
1399+
gParseField :: Options -> (Field -> Parser (f p)) -> Field -> Parser (f p)
13991400

14001401
-- Type with single nullary constructor
14011402
instance (Constructor c) => GFromField (C1 c U1) where
1402-
gParseField opts field = do
1403-
if field == expected then pure val else mempty
1403+
gParseField opts onFail field = do
1404+
if field == expected then pure val else onFail field
14041405
where
14051406
expected = encodeConstructor opts val
14061407
val :: C1 c U1 p
@@ -1409,13 +1410,18 @@ instance (Constructor c) => GFromField (C1 c U1) where
14091410

14101411
-- Type with single unary constructor
14111412
instance (FromField a) => GFromField (C1 c (S1 meta (K1 i a))) where
1412-
gParseField _ = fmap (M1 . M1 . K1) . parseField
1413+
gParseField _ onFail field =
1414+
fmap (M1 . M1 . K1) (parseField field) <|> onFail field
14131415
{-# INLINE gParseField #-}
14141416

14151417
-- Sum type
14161418
instance (GFromField c1, GFromField c2) => GFromField (c1 :+: c2) where
1417-
gParseField opts field =
1418-
fmap L1 (gParseField opts field) <|> fmap R1 (gParseField opts field)
1419+
gParseField opts onFail field =
1420+
case runParser $ gParseField opts mempty field of
1421+
Left _ -> case runParser $ gParseField opts mempty field of
1422+
Left _ -> onFail field
1423+
Right res -> pure $ R1 res
1424+
Right res -> pure $ L1 res
14191425
{-# INLINE gParseField #-}
14201426

14211427
class GToField f where

tests/UnitTests.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ genericFieldTests =
504504
[ testCase "encoding" $ toField Foo @?= "Foo"
505505
, testCase "decoding" $ runParser (parseField "Foo") @?= Right Foo ]
506506
, testCase "decoding failure" $ runParser (parseField "foo")
507-
@?= (Left "Expected \"Foo\"" :: Either String Foo)
507+
@?= (Left "Can't parseField of type Foo" :: Either String Foo)
508508
, testProperty "sum type roundtrip" (roundtripProp :: Bar -> Bool)
509509
, testGroup "constructor modifier"
510510
[ testCase "encoding" $ toField BazOne @?= "one"

0 commit comments

Comments
 (0)