Skip to content

Commit

Permalink
Use ResultMap to abstract functor
Browse files Browse the repository at this point in the history
  • Loading branch information
rexcfnghk committed Jun 16, 2024
1 parent 0fd736c commit 10a0e52
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
1 change: 1 addition & 0 deletions DataParser.Console/DataParser.Console.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<ItemGroup>
<Compile Include="Result.fs" />
<Compile Include="ResultBuilder.fs" />
<Compile Include="ResultMap.fs" />
<Compile Include="Core.fs" />
<Compile Include="FormatFiles.fs" />
<Compile Include="DataFiles.fs" />
Expand Down
26 changes: 15 additions & 11 deletions DataParser.Console/FileRead.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ open DataParser.Console.Core
open DataParser.Console.FormatFiles
open DataParser.Console.DataFiles
open System.IO
open ResultMap

let readAllSpecFiles folderPath =
let createFormatFileTuple (filePath: string) =
Expand Down Expand Up @@ -34,14 +35,17 @@ let readDataFiles folderPath =
(file, Path.GetFileNameWithoutExtension file)
}

let mapDataFilePath specs (filePath, fileName) =
let getSuccessfulKeys = Set.ofSeq << Map.keys << Map.filter (fun _ -> Result.isOk)

result {
let! DataFileName (dataFileName, _) = parseDataFileName fileName
let! dataFileFormat =
match Map.tryFind dataFileName specs with
| Some formatLines -> Result.bind (flip getDataFileFormat (filePath, fileName)) formatLines
| None -> Error [FileFormatNotFound (getSuccessfulKeys specs, dataFileName)]
return! parseDataFile dataFileFormat
}
let getDataFileFormats resultMap =
let folder (resultMap as ResultMap specs) state (filePath, fileName) =
match parseDataFileName fileName with
| Error e -> Map.add filePath (Error e) state
| Ok (DataFileName (formatName, _)) ->
let r =
match Map.tryFind formatName specs with
| Some formatLines ->
Result.bind (flip getDataFileFormat (filePath, fileName)) formatLines
| None -> Error [FileFormatNotFound (ResultMap.keys resultMap, formatName)]
Map.add filePath r state

Seq.fold (folder resultMap) Map.empty

17 changes: 12 additions & 5 deletions DataParser.Console/Program.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
open System
open DataParser.Console.FileRead
open DataParser.Console.FileWrite
open ResultMap

[<Literal>]
let specFolderPath = "./specs"
Expand All @@ -11,21 +12,27 @@ let dataFolderPath = "./data"
[<Literal>]
let outputFolderPath = "./output"

let okHandler = writeOutputFile outputFolderPath
let okHandler _ = writeOutputFile outputFolderPath

let errorHandler = List.iter (eprintfn "Error occurred during processing: %+A")
let errorHandler key errors = eprintfn $"Error occurred during processing format: {key}. Error is : %+A{errors}"

printfn "Reading spec files..."
let specs = readAllSpecFiles specFolderPath
let specs = ResultMap (readAllSpecFiles specFolderPath)

printfn "Retrieving data files..."
let dataFiles = readDataFiles dataFolderPath

printfn "Parsing data files..."
let dataFileParsedResults = Seq.map (mapDataFilePath specs) dataFiles
let parsedDateFileFormats =
dataFiles
|> getDataFileFormats specs
|> ResultMap

let dataFileParsedResults =
ResultMap.bindResult parseDataFile parsedDateFileFormats

printfn "Writing to output..."
Seq.iter (Result.biFoldMap okHandler errorHandler) dataFileParsedResults
ResultMap.biIter okHandler errorHandler dataFileParsedResults

printfn "Processing complete. Press Enter to exit."
ignore <| Console.ReadLine()
22 changes: 22 additions & 0 deletions DataParser.Console/ResultMap.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace ResultMap

type ResultMap<'TKey, 'TOkValue, 'TErrorValue when 'TKey : comparison> =
ResultMap of Map<'TKey, Result<'TOkValue, 'TErrorValue list>>

module ResultMap =
let map f (ResultMap x) =
x
|> Map.map (fun _ -> Result.map f)
|> ResultMap

let bindResult f (ResultMap x) =
x
|> Map.map (fun _ -> Result.bind f)
|> ResultMap

let keys (ResultMap x) = Set.ofSeq (Map.keys x)

let biIter f g (ResultMap x) =
let go k = function Ok v -> f k v | Error e -> g k e
Map.iter go x

0 comments on commit 10a0e52

Please sign in to comment.