Skip to content

Commit 638f213

Browse files
committed
first draft of a mechanism to construct values from .janno/.ssf fields depending on the poseidon package version
1 parent 0abb550 commit 638f213

File tree

8 files changed

+205
-191
lines changed

8 files changed

+205
-191
lines changed

src/Poseidon/CLI/Jannocoalesce.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Data.Text (pack, replace, unpack)
2525
import System.Directory (createDirectoryIfMissing)
2626
import System.FilePath (takeDirectory)
2727
import Text.Regex.TDFA ((=~))
28+
import Poseidon.PoseidonVersion (latestPoseidonVersion)
2829

2930
-- the source can be a single janno file, or a set of base directories as usual.
3031
data JannoSourceSpec = JannoSourceSingle FilePath | JannoSourceBaseDirs [FilePath]
@@ -48,7 +49,7 @@ data JannoCoalesceOptions = JannoCoalesceOptions
4849
runJannocoalesce :: JannoCoalesceOptions -> PoseidonIO ()
4950
runJannocoalesce (JannoCoalesceOptions sourceSpec target outSpec fields overwrite sKey tKey maybeStrip) = do
5051
JannoRows sourceRows <- case sourceSpec of
51-
JannoSourceSingle sourceFile -> readJannoFile [] sourceFile
52+
JannoSourceSingle sourceFile -> readJannoFile latestPoseidonVersion [] sourceFile
5253
JannoSourceBaseDirs sourceDirs -> do
5354
let pacReadOpts = defaultPackageReadOptions {
5455
_readOptIgnoreChecksums = True
@@ -57,7 +58,7 @@ runJannocoalesce (JannoCoalesceOptions sourceSpec target outSpec fields overwrit
5758
, _readOptOnlyLatest = True
5859
}
5960
getJointJanno <$> readPoseidonPackageCollection pacReadOpts sourceDirs
60-
JannoRows targetRows <- readJannoFile [] target
61+
JannoRows targetRows <- readJannoFile latestPoseidonVersion [] target
6162

6263
newJanno <- makeNewJannoRows sourceRows targetRows fields overwrite sKey tKey maybeStrip
6364

@@ -123,7 +124,7 @@ mergeRow cp targetRow sourceRow fields overwrite sKey tKey = do
123124
-- fill in the target row with dummy values for desired fields that might not be present yet
124125
targetComplete = HM.union targetRowRecord (HM.fromList $ map (, BSC.empty) sourceKeysDesired)
125126
newRowRecord = HM.mapWithKey fillFromSource targetComplete
126-
parseResult = Csv.runParser . parseJannoRowFromNamedRecord [] $ newRowRecord
127+
parseResult = Csv.runParser . parseJannoRowFromNamedRecord latestPoseidonVersion [] $ newRowRecord
127128
logInfo $ "matched target " ++ BSC.unpack (targetComplete HM.! BSC.pack tKey) ++
128129
" with source " ++ BSC.unpack (sourceRowRecord HM.! BSC.pack sKey)
129130
case parseResult of

src/Poseidon/CLI/Validate.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import Data.List (groupBy, intercalate, sortOn)
2828
import Data.Yaml (decodeEither')
2929
import Poseidon.EntityTypes (IndividualInfo (..))
3030
import System.Exit (exitFailure, exitSuccess)
31+
import Poseidon.PoseidonVersion (latestPoseidonVersion)
3132

3233
-- | A datatype representing command line options for the validate command
3334
data ValidateOptions = ValidateOptions
@@ -106,12 +107,12 @@ runValidate (ValidateOptions (ValPlanGeno geno) _ _ noExitCode _) = do
106107
conclude True noExitCode
107108
runValidate (ValidateOptions (ValPlanJanno path) mandatoryJannoCols _ noExitCode _) = do
108109
logInfo $ "Validating: " ++ path
109-
(JannoRows entries) <- readJannoFile mandatoryJannoCols path
110+
(JannoRows entries) <- readJannoFile latestPoseidonVersion mandatoryJannoCols path
110111
logInfo $ "All " ++ show (length entries) ++ " entries are valid"
111112
conclude True noExitCode
112113
runValidate (ValidateOptions (ValPlanSSF path) _ mandatorySSFCols noExitCode _) = do
113114
logInfo $ "Validating: " ++ path
114-
(SeqSourceRows entries) <- readSeqSourceFile mandatorySSFCols path
115+
(SeqSourceRows entries) <- readSeqSourceFile latestPoseidonVersion mandatorySSFCols path
115116
logInfo $ "All " ++ show (length entries) ++ " entries are valid"
116117
conclude True noExitCode
117118
runValidate (ValidateOptions (ValPlanBib path) _ _ noExitCode _) = do

src/Poseidon/ColumnTypesJanno.hs

Lines changed: 50 additions & 50 deletions
Large diffs are not rendered by default.

src/Poseidon/ColumnTypesSSF.hs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ data SSFUDG =
2525
deriving (Eq, Ord, Generic, Enum, Bounded)
2626

2727
instance Makeable SSFUDG where
28-
make x
28+
make _ x
2929
| x == "minus" = pure SSFMinus
3030
| x == "half" = pure SSFHalf
3131
| x == "plus" = pure SSFPlus
@@ -37,7 +37,7 @@ instance Show SSFUDG where
3737
show SSFHalf = "half"
3838
show SSFPlus = "plus"
3939
instance Csv.ToField SSFUDG where toField x = Csv.toField $ show x
40-
instance Csv.FromField SSFUDG where parseField = parseTypeCSV "udg"
40+
instance FromFieldVersioned SSFUDG where parseFieldVersioned pv = parseTypeCSV pv "udg"
4141

4242
-- | A datatype for the library_built .ssf column
4343
data SSFLibraryBuilt =
@@ -46,7 +46,7 @@ data SSFLibraryBuilt =
4646
deriving (Eq, Ord, Generic, Enum, Bounded)
4747

4848
instance Makeable SSFLibraryBuilt where
49-
make x
49+
make _ x
5050
| x == "ds" = pure SSFDS
5151
| x == "ss" = pure SSFSS
5252
| otherwise = fail $ "library_built is set to " ++ show x ++ ". " ++
@@ -56,14 +56,14 @@ instance Show SSFLibraryBuilt where
5656
show SSFDS = "ds"
5757
show SSFSS = "ss"
5858
instance Csv.ToField SSFLibraryBuilt where toField x = Csv.toField $ show x
59-
instance Csv.FromField SSFLibraryBuilt where parseField = parseTypeCSV "library_built"
59+
instance FromFieldVersioned SSFLibraryBuilt where parseFieldVersioned pv = parseTypeCSV pv "library_built"
6060

6161
-- | A datatype for the sample_accession .ssf column
6262
newtype SSFAccessionIDSample = SSFAccessionIDSample AccessionID
6363
deriving (Eq, Ord, Generic)
6464

6565
instance Makeable SSFAccessionIDSample where
66-
make x = do
66+
make _ x = do
6767
accID <- makeAccessionID x
6868
return $ SSFAccessionIDSample accID
6969
instance Suspicious SSFAccessionIDSample where
@@ -76,14 +76,14 @@ instance Suspicious SSFAccessionIDSample where
7676
instance Show SSFAccessionIDSample where
7777
show (SSFAccessionIDSample x) = show x
7878
instance Csv.ToField SSFAccessionIDSample where toField x = Csv.toField $ show x
79-
instance Csv.FromField SSFAccessionIDSample where parseField = parseTypeCSV "sample_accession"
79+
instance FromFieldVersioned SSFAccessionIDSample where parseFieldVersioned pv = parseTypeCSV pv "sample_accession"
8080

8181
-- | A datatype for the study_accession .ssf column
8282
newtype SSFAccessionIDStudy = SSFAccessionIDStudy AccessionID
8383
deriving (Eq, Ord, Generic)
8484

8585
instance Makeable SSFAccessionIDStudy where
86-
make x = do
86+
make _ x = do
8787
accID <- makeAccessionID x
8888
return $ SSFAccessionIDStudy accID
8989
instance Suspicious SSFAccessionIDStudy where
@@ -96,14 +96,14 @@ instance Suspicious SSFAccessionIDStudy where
9696
instance Show SSFAccessionIDStudy where
9797
show (SSFAccessionIDStudy x) = show x
9898
instance Csv.ToField SSFAccessionIDStudy where toField x = Csv.toField $ show x
99-
instance Csv.FromField SSFAccessionIDStudy where parseField = parseTypeCSV "study_accession"
99+
instance FromFieldVersioned SSFAccessionIDStudy where parseFieldVersioned pv = parseTypeCSV pv "study_accession"
100100

101101
-- | A datatype for the run_accession .ssf column
102102
newtype SSFAccessionIDRun = SSFAccessionIDRun AccessionID
103103
deriving (Eq, Ord, Generic)
104104

105105
instance Makeable SSFAccessionIDRun where
106-
make x = do
106+
make _ x = do
107107
accID <- makeAccessionID x
108108
return $ SSFAccessionIDRun accID
109109
instance Suspicious SSFAccessionIDRun where
@@ -115,7 +115,7 @@ instance Suspicious SSFAccessionIDRun where
115115
instance Show SSFAccessionIDRun where
116116
show (SSFAccessionIDRun x) = show x
117117
instance Csv.ToField SSFAccessionIDRun where toField x = Csv.toField $ show x
118-
instance Csv.FromField SSFAccessionIDRun where parseField = parseTypeCSV "run_accession"
118+
instance FromFieldVersioned SSFAccessionIDRun where parseFieldVersioned pv = parseTypeCSV pv "run_accession"
119119

120120
-- | A datatype for the sample_alias .ssf column
121121
newtype SSFSampleAlias = SSFSampleAlias T.Text deriving (Eq, Ord)
@@ -130,7 +130,7 @@ newtype SSFFirstPublicSimpleDate = SSFFirstPublicSimpleDate Day
130130
deriving (Eq, Ord, Generic)
131131

132132
instance Makeable SSFFirstPublicSimpleDate where
133-
make x = do
133+
make _ x = do
134134
case parseTimeM False defaultTimeLocale "%Y-%-m-%-d" (T.unpack x) :: Maybe Day of
135135
Nothing -> fail $ "first_public date " ++ T.unpack x ++
136136
" is not a correct date in the format YYYY-MM-DD."
@@ -140,15 +140,15 @@ instance Show SSFFirstPublicSimpleDate where
140140
show (SSFFirstPublicSimpleDate x) = formatTime defaultTimeLocale "%Y-%-m-%-d" x
141141
instance Csv.ToField SSFFirstPublicSimpleDate where
142142
toField (SSFFirstPublicSimpleDate x) = Csv.toField $ show x
143-
instance Csv.FromField SSFFirstPublicSimpleDate where
144-
parseField = parseTypeCSV "first_public"
143+
instance FromFieldVersioned SSFFirstPublicSimpleDate where
144+
parseFieldVersioned pv = parseTypeCSV pv "first_public"
145145

146146
-- | A datatype for the last_updated .ssf column
147147
newtype SSFLastUpdatedSimpleDate = SSFLastUpdatedSimpleDate Day
148148
deriving (Eq, Ord, Generic)
149149

150150
instance Makeable SSFLastUpdatedSimpleDate where
151-
make x = do
151+
make _ x = do
152152
case parseTimeM False defaultTimeLocale "%Y-%-m-%-d" (T.unpack x) :: Maybe Day of
153153
Nothing -> fail $ "last_updated date " ++ T.unpack x ++
154154
" is not a correct date in the format YYYY-MM-DD."
@@ -158,8 +158,8 @@ instance Show SSFLastUpdatedSimpleDate where
158158
show (SSFLastUpdatedSimpleDate x) = formatTime defaultTimeLocale "%Y-%-m-%-d" x
159159
instance Csv.ToField SSFLastUpdatedSimpleDate where
160160
toField (SSFLastUpdatedSimpleDate x) = Csv.toField $ show x
161-
instance Csv.FromField SSFLastUpdatedSimpleDate where
162-
parseField = parseTypeCSV "last_updated"
161+
instance FromFieldVersioned SSFLastUpdatedSimpleDate where
162+
parseFieldVersioned pv = parseTypeCSV pv "last_updated"
163163

164164
-- | A datatype for the instrument_model .ssf column
165165
newtype SSFInstrumentModel = SSFInstrumentModel T.Text deriving (Eq, Ord)
@@ -190,48 +190,48 @@ newtype SSFFastqFTPURI = SSFFastqFTPURI T.Text
190190
deriving (Eq, Ord, Generic)
191191

192192
instance Makeable SSFFastqFTPURI where
193-
make x
193+
make _ x
194194
| isURIReference (T.unpack x) = pure $ SSFFastqFTPURI x
195195
| otherwise = fail $ "fastq_ftp entry " ++ show x ++
196196
" is not a well-structured URI."
197197
instance Suspicious SSFFastqFTPURI where inspect _ = Nothing
198198
instance Show SSFFastqFTPURI where show (SSFFastqFTPURI x) = T.unpack x
199199
instance Csv.ToField SSFFastqFTPURI where toField x = Csv.toField $ show x
200-
instance Csv.FromField SSFFastqFTPURI where parseField = parseTypeCSV "fastq_ftp"
200+
instance FromFieldVersioned SSFFastqFTPURI where parseFieldVersioned pv = parseTypeCSV pv "fastq_ftp"
201201

202202
-- | A datatype for the fastq_aspera .ssf column
203203
newtype SSFFastqASPERAURI = SSFFastqASPERAURI T.Text
204204
deriving (Eq, Ord, Generic)
205205

206206
instance Makeable SSFFastqASPERAURI where
207-
make x
207+
make _ x
208208
| isURIReference (T.unpack x) = pure $ SSFFastqASPERAURI x
209209
| otherwise = fail $ "fastq_aspera entry " ++ show x ++
210210
" is not a well-structured URI."
211211
instance Suspicious SSFFastqASPERAURI where inspect _ = Nothing
212212
instance Show SSFFastqASPERAURI where show (SSFFastqASPERAURI x) = T.unpack x
213213
instance Csv.ToField SSFFastqASPERAURI where toField x = Csv.toField $ show x
214-
instance Csv.FromField SSFFastqASPERAURI where parseField = parseTypeCSV "fastq_aspera"
214+
instance FromFieldVersioned SSFFastqASPERAURI where parseFieldVersioned pv = parseTypeCSV pv "fastq_aspera"
215215

216216
-- | A datatype for the fastq_bytes .ssf column
217217
newtype SSFFastqBytes = SSFFastqBytes Integer deriving (Eq, Ord, Generic)
218218

219219
instance Makeable SSFFastqBytes where
220-
make x =
220+
make _ x =
221221
case T.decimal x of
222222
Left e -> fail $ "fastq_bytes can not be converted to Integer because " ++ e
223223
Right (num, "") -> pure $ SSFFastqBytes num
224224
Right (_, rest) -> fail $ "fastq_bytes can not be converted to Integer, because of a trailing " ++ show rest
225225
instance Suspicious SSFFastqBytes where inspect _ = Nothing
226226
instance Show SSFFastqBytes where show (SSFFastqBytes x) = show x
227227
instance Csv.ToField SSFFastqBytes where toField (SSFFastqBytes x) = Csv.toField x
228-
instance Csv.FromField SSFFastqBytes where parseField = parseTypeCSV "fastq_bytes"
228+
instance FromFieldVersioned SSFFastqBytes where parseFieldVersioned pv = parseTypeCSV pv "fastq_bytes"
229229

230230
-- | A datatype for the fastq_md5 .ssf column
231231
newtype SSFFastqMD5 = SSFFastqMD5 T.Text deriving (Eq, Ord, Generic)
232232

233233
instance Makeable SSFFastqMD5 where
234-
make x
234+
make _ x
235235
| isMD5Hash x = pure $ SSFFastqMD5 x
236236
| otherwise = fail $ "fastq_md5 " ++ show x ++
237237
" does not contain a well-structured MD5 hash"
@@ -240,13 +240,13 @@ isMD5Hash x = T.length x == 32 && T.all isHexDigit x
240240
instance Suspicious SSFFastqMD5 where inspect _ = Nothing
241241
instance Show SSFFastqMD5 where show (SSFFastqMD5 x) = T.unpack x
242242
instance Csv.ToField SSFFastqMD5 where toField x = Csv.toField $ show x
243-
instance Csv.FromField SSFFastqMD5 where parseField = parseTypeCSV "fastq_md5"
243+
instance FromFieldVersioned SSFFastqMD5 where parseFieldVersioned pv = parseTypeCSV pv "fastq_md5"
244244

245245
-- | A datatype for the fastq_bytes .ssf column
246246
newtype SSFReadCount = SSFReadCount Integer deriving (Eq, Ord, Generic)
247247

248248
instance Makeable SSFReadCount where
249-
make x =
249+
make _ x =
250250
case T.signed T.decimal x of -- the ENA uses -1 in case the read count failed
251251
Left e -> fail $ "read_count can not be converted to Integer because " ++ e
252252
Right (num, "") ->
@@ -260,31 +260,31 @@ instance Suspicious SSFReadCount where
260260
| otherwise = pure []
261261
instance Show SSFReadCount where show (SSFReadCount x) = show x
262262
instance Csv.ToField SSFReadCount where toField (SSFReadCount x) = Csv.toField x
263-
instance Csv.FromField SSFReadCount where parseField = parseTypeCSV "read_count"
263+
instance FromFieldVersioned SSFReadCount where parseFieldVersioned pv = parseTypeCSV pv "read_count"
264264

265265
-- | A datatype for the submitted_ftp .ssf column
266266
newtype SSFSubmittedFTPURI = SSFSubmittedFTPURI T.Text
267267
deriving (Eq, Ord, Generic)
268268

269269
instance Makeable SSFSubmittedFTPURI where
270-
make x
270+
make _ x
271271
| isURIReference (T.unpack x) = pure $ SSFSubmittedFTPURI x
272272
| otherwise = fail $ "submitted_ftp entry " ++ show x ++
273273
" is not a well-structured URI."
274274
instance Suspicious SSFSubmittedFTPURI where inspect _ = Nothing
275275
instance Show SSFSubmittedFTPURI where show (SSFSubmittedFTPURI x) = T.unpack x
276276
instance Csv.ToField SSFSubmittedFTPURI where toField x = Csv.toField $ show x
277-
instance Csv.FromField SSFSubmittedFTPURI where parseField = parseTypeCSV "submitted_ftp"
277+
instance FromFieldVersioned SSFSubmittedFTPURI where parseFieldVersioned pv = parseTypeCSV pv "submitted_ftp"
278278

279279
-- | A datatype for the submitted_md5 .ssf column
280280
newtype SSFSubmittedMD5 = SSFSubmittedMD5 T.Text deriving (Eq, Ord, Generic)
281281

282282
instance Makeable SSFSubmittedMD5 where
283-
make x
283+
make _ x
284284
| isMD5Hash x = pure $ SSFSubmittedMD5 x
285285
| otherwise = fail $ "submitted_md5 " ++ show x ++
286286
" does not contain a well-structured MD5 hash"
287287
instance Suspicious SSFSubmittedMD5 where inspect _ = Nothing
288288
instance Show SSFSubmittedMD5 where show (SSFSubmittedMD5 x) = T.unpack x
289289
instance Csv.ToField SSFSubmittedMD5 where toField x = Csv.toField $ show x
290-
instance Csv.FromField SSFSubmittedMD5 where parseField = parseTypeCSV "submitted_md5"
290+
instance FromFieldVersioned SSFSubmittedMD5 where parseFieldVersioned pv = parseTypeCSV pv "submitted_md5"

src/Poseidon/ColumnTypesUtils.hs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@ import Language.Haskell.TH (Con (..), Dec (..), DecsQ, Info (..),
3030
varE, varP)
3131
import qualified Text.Parsec as P
3232
import qualified Text.Parsec.String as P
33+
import Poseidon.PoseidonVersion (PoseidonVersion)
34+
35+
-- a typeclass like cassavas FromField, but aware of PoseidonVersions
36+
class FromFieldVersioned a where
37+
parseFieldVersioned :: PoseidonVersion -> Csv.Field -> Csv.Parser a
38+
39+
-- legacy instance for Poseidon_ID and Group_Name; can be removed eventually
40+
instance FromFieldVersioned String where parseFieldVersioned _ = Csv.parseField
3341

3442
-- a typeclass for types with smart constructors
3543
class Makeable a where
36-
make :: MonadFail m => T.Text -> m a
44+
make :: MonadFail m => PoseidonVersion -> T.Text -> m a
3745

3846
-- a typeclass for .csv/.tsv column types that may require a logged warning when read
3947
class Suspicious a where
@@ -57,22 +65,22 @@ inspectEachField =
5765
. unZ . unSOP . Generics.SOP.from
5866

5967
-- helper functions
60-
parseTypeCSV :: forall a m. (MonadFail m, Makeable a, Typeable a) => String -> S.ByteString -> m a
61-
parseTypeCSV colname x = case T.decodeUtf8' x of
68+
parseTypeCSV :: forall a m. (MonadFail m, Makeable a, Typeable a) => PoseidonVersion -> String -> S.ByteString -> m a
69+
parseTypeCSV pv colname x = case T.decodeUtf8' x of
6270
Left e -> fail $ show e ++ " in column " ++ colname
63-
Right t -> make $ T.strip t
71+
Right t -> make pv $ T.strip t
6472

6573
-- template haskell function to generate repetitive instances
6674
makeInstances :: Name -> String -> DecsQ
6775
makeInstances name col = do
6876
TyConI (NewtypeD _ _ _ _ (NormalC conName _) _) <- reify name
6977
let x = mkName "x"
7078
[d|
71-
instance Makeable $(conT name) where make txt = return $ $(conE conName) txt
79+
instance Makeable $(conT name) where make _ txt = return $ $(conE conName) txt
7280
instance Suspicious $(conT name) where inspect _ = Nothing
7381
instance Show $(conT name) where show $(conP conName [varP x]) = T.unpack $(varE x)
7482
instance Csv.ToField $(conT name) where toField $(conP conName [varP x]) = Csv.toField $(varE x)
75-
instance Csv.FromField $(conT name) where parseField = parseTypeCSV col
83+
instance FromFieldVersioned $(conT name) where parseFieldVersioned pv = parseTypeCSV pv col
7684
|]
7785

7886
-- general encoding/decoding options
@@ -113,13 +121,13 @@ checkMandatory m mandatory =
113121
Nothing -> fail ("Missing value in mandatory column: " <> Bchs.unpack mandatory)
114122
Just _ -> pure ()
115123

116-
filterLookup :: Csv.FromField a => Csv.NamedRecord -> Bchs.ByteString -> Csv.Parser a
117-
filterLookup m name = case cleanInput $ HM.lookup name m of
124+
filterLookup :: FromFieldVersioned a => PoseidonVersion -> Csv.NamedRecord -> Bchs.ByteString -> Csv.Parser a
125+
filterLookup pv m name = case cleanInput $ HM.lookup name m of
118126
Nothing -> fail $ "Missing value in mandatory column: " <> Bchs.unpack name
119-
Just x -> Csv.parseField x
127+
Just x -> parseFieldVersioned pv x
120128

121-
filterLookupOptional :: Csv.FromField a => Csv.NamedRecord -> Bchs.ByteString -> Csv.Parser (Maybe a)
122-
filterLookupOptional m name = maybe (pure Nothing) Csv.parseField . cleanInput $ HM.lookup name m
129+
filterLookupOptional :: FromFieldVersioned a => PoseidonVersion -> Csv.NamedRecord -> Bchs.ByteString -> Csv.Parser (Maybe a)
130+
filterLookupOptional pv m name = maybe (pure Nothing) (\bs -> Just <$> parseFieldVersioned pv bs) . cleanInput $ HM.lookup name m
123131

124132
cleanInput :: Maybe Bchs.ByteString -> Maybe Bchs.ByteString
125133
cleanInput Nothing = Nothing
@@ -143,8 +151,8 @@ getMaybeListColumn (Just x) = getListColumn x
143151

144152
instance (Csv.ToField a, Show a) => Csv.ToField (ListColumn a) where
145153
toField x = Bchs.intercalate ";" $ L.map Csv.toField $ getListColumn x
146-
instance (Csv.FromField a) => Csv.FromField (ListColumn a) where
147-
parseField x = fmap ListColumn . mapM Csv.parseField $ Bchs.splitWith (==';') x
154+
instance (FromFieldVersioned a) => FromFieldVersioned (ListColumn a) where
155+
parseFieldVersioned pv x = fmap ListColumn . mapM (parseFieldVersioned pv) $ Bchs.splitWith (==';') x
148156

149157
-- helper functions for reformatting parser errors
150158
removeUselessSuffix :: String -> String

0 commit comments

Comments
 (0)