Parsing Path type

77 views Asked by At

I was trying to make an instance for the Path type. https://hackage.haskell.org/package/path

If I use the generic.

instance FromDhall (Path Rel Dir)

This doesn't do any normalisation of directories. I initially assumed this would piggyback off the defined FromJSON instances which in turn call parseRelDir etc, but that's not the case, and when I tried to implement this manually I realised I'm quite in over my head. What's the way to do this?

1

There are 1 answers

2
Gabriella Gonzalez On

The derived instance will use the shape of the Path datatype. Even though the Path constructor is not exposed it still provides a Generic instance, which is enough for the FromDhall instance to derive something.

In this case, since Path is internally defined as:

newtype Path b t = Path FilePath

… then the derived FromDhall instance will expect a Dhall value of something like this type:

{ _1 : Text }

… which is the derived Dhall type for a data type with 1 anonymous field that is a String/FilePath.

This is probably not what you wanted (as you noted), so if you want different behavior you will need to implement the FromDhall instance yourself.

So what you will probably want to write is something like:

instance FromDhall (Path Rel Dir) where
    -- Our `Decoder` will be similar to the `filePathDecoder`,
    -- except with a different `extract` function
    autoWith options =
        Decoder
            { extract = extractPath
            , expected = expectedPath
            }
      where
        filePathDecoder :: Decoder FilePath
        filePathDecoder = autoWith options

        -- To extract a `Path`, first extract a `FilePath`
        -- and attempt to parse it into a `Path`
        extractPath expression =
          case extract filePathDecoder expression of
              Success filepath ->
                  case Path.parseRelDir filePath of
                      Left exception ->
                          Dhall.extractError (Text.pack (show exception))
                      Right path ->
                          Success path
              Failure e -> Failure e

        -- The expected Dhall type for a `Path` is the same
        -- as for a `FilePath`
        expectedPath = expected filePathDecoder