Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IO functions for reading. Remove PoolMetadataFile type #5194

Merged
merged 6 commits into from
May 10, 2023

Conversation

newhoggy
Copy link
Contributor

@newhoggy newhoggy commented May 5, 2023

Description

Add IO functions for reading files.
Remove PoolMetadataFile type and use File type instead.
Work around some type-inference issues that shouldn't exist.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. These may include:
    • golden tests
    • property tests
    • roundtrip tests
    • integration tests
      See Runnings tests for more details
  • Any changes are noted in the CHANGELOG.md for affected package
  • The version bounds in .cabal files are updated
  • CI passes. See note on CI. The following CI checks are required:
    • Code is linted with hlint. See .github/workflows/check-hlint.yml to get the hlint version
    • Code is formatted with stylish-haskell. See .github/workflows/stylish-haskell.yml to get the stylish-haskell version
    • Code builds on Linux, MacOS and Windows for ghc-8.10.7 and ghc-9.2.7
  • Self-reviewed the diff

Note on CI

If your PR is from a fork, the necessary CI jobs won't trigger automatically for security reasons.
You will need to get someone with write privileges. Please contact IOG node developers to do this
for you.

@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch from 4c3373f to 65aa5e9 Compare May 5, 2023 02:10
@newhoggy newhoggy marked this pull request as ready for review May 5, 2023 02:10
@@ -76,7 +76,7 @@ newtype File content (direction :: FileDirection) = File
handleFileForWritingWithOwnerPermission
:: FilePath
-> (Handle -> IO ())
-> IO (Either (FileError ()) ())
Copy link
Contributor Author

@newhoggy newhoggy May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't be () because we wan't to use the functions for reading things with e other than ().

The fact that e is here at all is problematic. e is for decode errors, but why should functions purely used for reading and writing files and do no decode at all have to concern themselves with decode errors? Having the e here produce type-inference problems down the line.

See #5194 (comment)

@@ -66,7 +67,7 @@ createFileWithOwnerPermissions :: HasTextEnvelope a => File () Out -> a -> Prope
createFileWithOwnerPermissions targetfp value = do
result <- liftIO $ writeLazyByteStringFileWithOwnerPermissions targetfp $ textEnvelopeToJSON Nothing value
case result of
Left err -> failWith Nothing $ displayError err
Left err -> failWith Nothing $ displayError @(FileError ()) err
Copy link
Contributor Author

@newhoggy newhoggy May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler needs to infer a concrete type for e because it "needs" to display the error. The compile doesn't actually need the display the error because the constructor that has e is never used, but the compiler doesn't know that. We have to help the compiler by fixing e = () because there is an Error () instance this work.

It's unpleasant we have to help the compiler infer a type to display an error that never gets displayed, but our errors are tightly coupled.

@newhoggy newhoggy requested a review from carbolymer May 5, 2023 02:32
@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch from 65aa5e9 to f2e11b9 Compare May 5, 2023 05:11
@@ -117,18 +123,39 @@ handleFileForWritingWithOwnerPermission path f = do
(targetDir, targetFile) = splitFileName path
#endif

readByteStringFile :: ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh, a typeclass would work here better instead of having all those specialized functions.

Copy link
Contributor Author

@newhoggy newhoggy May 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an objection to type classes.

You're welcome to put up a PR and we can see what it looks like.

@carbolymer
Copy link
Contributor

carbolymer commented May 5, 2023

data FileError e = FileError FilePath e
                 | FileErrorTempFile
                     FilePath
                     -- ^ Target path
                     FilePath
                     -- ^ Temporary path
                     Handle
                 | FileIOError FilePath IOException
  deriving (Show, Eq, Functor)

Firstly, do we really need to have a type parameter in FileError for explicit errors for files? This seems overly specific and unnecessary for just error handling. This type parameter also does not make much sense for constructors which do not carry a value of type e and requires plugging with something like (), which is painful, like @newhoggy mentions.

My suggestion here would be to go similarly to https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Exception.html : remove type parameter, and make type existential and provide access to the field value via existing Error class. And in the rare need for handling particular error type returned, we could just simply cast and handle it. What do you think?

@newhoggy
Copy link
Contributor Author

newhoggy commented May 6, 2023

These are the types of e that are currently used and we have Error instances for them:

CardanoAddressSigningKeyConversionError
IOException
InputDecodeError
JsonDecodeError
ScriptDecodeError
TextEnvelopeCddlError
TextEnvelopeError

We need to be able to throw these error types along side File ones because functions exist that produce both kinds of errors.

This is another example of where oops helps.

The purely file functions can throw FileError, purely decode functions can throw DecodeError and functions that do both can throw them side-by-side:

readByteStringFile :: ()
  => e `CouldBe` FileError
  => File content In
  -> ExceptT (Variant e) IO ByteString

decodeMyType :: ()
  => e `CouldBe` DecodeError
  => ByteString
  -> ExceptT (Variant e) IO MyType

readFileAndDecodeMyType :: ()
  => e `CouldBe` FileError
  => e `CouldBe` DecodeError
  => File MyType In
  => ByteString
  -> ExceptT (Variant e) IO MyType
readFileAndDecodeMyType file = readByteStringFile file >>= decodeMyType

Full separation of concerns. We don't have to:

  • invent new error types to contain other error types
  • find a module to put those types in and debate where they should go
  • translate between error types because functions to marshal them through functions because we can only throw one error type at a time
  • couple different kinds of errors and make functions declare errors that are never thrown
  • catch errors with constructors that are never thrown
  • write code for things that never happen.

@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch from 65269e6 to f1f728c Compare May 6, 2023 06:26
Copy link
Contributor

@Jimbo4350 Jimbo4350 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch from f1f728c to 2266694 Compare May 9, 2023 18:09
@newhoggy newhoggy enabled auto-merge May 9, 2023 18:09
@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch 2 times, most recently from bd92209 to 6fab19a Compare May 10, 2023 01:30
@newhoggy newhoggy added this pull request to the merge queue May 10, 2023
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch May 10, 2023
@newhoggy newhoggy force-pushed the newhoggy/io-functions-for-reading branch from 6fab19a to ad1e3b6 Compare May 10, 2023 04:02
@newhoggy newhoggy added this pull request to the merge queue May 10, 2023
Merged via the queue into master with commit cf540ab May 10, 2023
@iohk-bors iohk-bors bot deleted the newhoggy/io-functions-for-reading branch May 10, 2023 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants