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

Dynamically check FsPath invariants #73

Open
jorisdral opened this issue Jun 6, 2024 · 0 comments
Open

Dynamically check FsPath invariants #73

jorisdral opened this issue Jun 6, 2024 · 0 comments

Comments

@jorisdral
Copy link
Collaborator

jorisdral commented Jun 6, 2024

First suggested in #72 (comment). FsPath has a number of invariants, and we currently rely on the user to satisfy them. It might be nice to check these invariants dynamically, while also providing an escape hatch for users in case they want to skip the check. For example:

newtype FsPath = UnsafeFsPath { fsPathToList :: [Strict.Text] }
  deriving (Eq, Ord, Generic)
  deriving newtype NFData

invariant :: FsPath -> Bool
invariant (UnsafeFsPath xs) = all p xs
 where p x = -- Paths are monotonic
             x /= ".."
          && -- Paths can not have empty directory/file names
             not (any Strict.null xs)
          && -- There are no path separators in individual names
             not (Text.any (`Text.elem` allPathSeparators) x)

allPathSeparators :: Text
allPathSeparators = Text.pack (Posix.pathSeparators ++ Windows.pathSeparators)

unsafeFsPathFromList :: [Strict.Text] -> FsPath
unsafeFsPathFromList xs = assert (invariant fsp) $ fsp
  where fsp = UnsafeFsPath (force xs)

fsPathFromList :: [Strict.Text] -> Maybe FsPath
fsPathFromList xs
  | invariant fsp = Just fsp
  | otherwise     = Nothing
  where fsp = UnsafeFsPath (force xs)

Note two things in the example above:

  • Both unsafeFsPathFromList and fsPathFromList ensure that the resulting FsPath contains no thunks my using force. Maybe we want to assert instead that the FsPath contains no thunks in unsafeFsPathFromList, and have the user ensure that fact.
  • To ensure similar behaviour across OS distributions, invariant checks do not depend on the underlying OS distribution, hence allPathSeparators.

We should also consider whether this design pattern is overkill: in practice, users are probably unlikely to use non-sensible path names

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

No branches or pull requests

1 participant