Add FromField instance for Maybe #6

Closed
tibbe opened this Issue Sep 7, 2012 · 6 comments

3 participants

@tibbe
Collaborator

It could be useful to have a FromField instance for Maybe that returns Nothing if the string is empty. Might also be worth adding an instance for Either. Maybe it will also make sense to do the same for FromRecord and FromNamedRecord.

@basvandijk

Note that issue #12 makes Maybe an instance of FromField and ToField.

@tibbe
Collaborator

Done in 19bc4ca.

@tibbe tibbe closed this Nov 20, 2012
@plredmond
> runParser $ parseField (pack "23") :: Either String (Maybe Int)
Right (Just 23)
> runParser $ parseField (pack "a") :: Either String (Maybe Int)
Left "expected Int, got \"a\" (Failed reading: takeWhile1)"

The behavior in this second example seems really unintuitive to me. In my code this behavior results in the whole file failing to parse. Since I said set the type to Maybe Int shouldn't failure be represented by Right Nothing (failure of the current field), rather than Left "..." (failure of the whole parse).

This would be ideal:

> runParser $ parseField (pack "a") :: Either String (Maybe Int)
Right Nothing

What's the reason for the current implementation's behavior?

@plredmond

Here's a FromField instance for a Maybe clone which behaves as I describe:

data Maybe' a = Just' a | Nothing' deriving (Show)

instance (Csv.FromField a) => Csv.FromField (Maybe' a) where
    parseField = A.pure
               . either (const Nothing') Just'
               . Csv.runParser
               . Csv.parseField

This parses the type parameter, decides whether success occurred, and packages it up in the appropriate Maybe' constructor. If the parse failed, it doesn't take down everything with it.

(FYI, The file I'm parsing is from kaggle.com contains a few columns which are usually Int, but sometimes contain "na", and when Maybe Int fails it stops the whole file from parsing. Maybe' Int works for me, but maybe it's not what you want for Cassava.)

@tibbe
Collaborator

You can use the Either instance of FromField:

ghci> runParser $ parseField (pack "a") :: Either String (Either ByteString Int)
Right (Left "a")

The Maybe instance is not for failures, but for empty fields.

@plredmond

Noted! Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment