Skip to content

Automatic (TH) PathPiece generation is poorly documented, and confusing #649

Open

Description

@tebello-thejane

The documentation for mkPersist says

Create data types and appropriate PersistEntity instances for the given EntityDefs. Works well with the persist quasi-quoter.

I'm struggling to understand why it also creates PathPiece instances. In particular, I have hit a confusing issue where, with more than two tables being defined, using an enum type (whose instances where generated via derivePersistField) in the one table causes the compiler to complain that the data type does not have the appropriate path-pieces instances, but enums in another table do not cause the same error.

The source code for the module reads

-- | declare the key type and associated instances
-- @'PathPiece'@, @'ToHttpApiData'@ and @'FromHttpApiData'@ instances are only generated for a Key with one field
mkKeyTypeDec :: MkPersistSettings → EntityDef → Q (Dec, [Dec])

What does this even mean?? Note that my project does not use Yesod (yet), so I'm finding it difficult to justify creating PathPiece and *HttpApiData instances just to satisfy the compiler when there aren't any actual paths in the code base, or any other hint of HTTP.

On a possibly-related note, declaring DeriveGeneric and DeriveAnyClass as default extensions in my project causes mkPersist to blow up and start complaining about missing Generic instances. That is, I guess this might be a weird extensions issue, but right now my guesses are worthless.

If necessary, I can try and create a minimal example producing the issue. But I'm hoping this rings a bell and has been encountered by someone else before.

Activity

  1. tebello-thejane commented on Jan 12, 2017

    @tebello-thejane
    Author

    Here is a minimal example.

    In a separate module, we have:

    import Database.Persist.TH
    
    data Bug = Ant | Bee | Roach deriving (Show, Read, Eq, Ord)
    derivePersistField "Bug"        

    Then our main program has:

    share [mkPersist sqlSettings] [persistLowerCase|
    Foo                                                                          
        bar Bug
        Primary idea
     |]    

    The compiler will complain with

    Main.hs:10:1: error:
        • No instance for (path-pieces-0.2.1:Web.PathPieces.PathPiece Bug)
            arising from the 'deriving' clause of a data type declaration
          Possible fix:
            use a standalone 'deriving instance' declaration,
              so you can specify the instance context yourself
        • When deriving the instance for (path-pieces-0.2.1:Web.PathPieces.PathPiece
                                            (Key Foo))
    
    Main.hs:10:1: error:
        • No instance for (http-api-data-0.2.4:Web.HttpApiData.Internal.ToHttpApiData
                             Bug)
            arising from the 'deriving' clause of a data type declaration
          Possible fix:
            use a standalone 'deriving instance' declaration,
              so you can specify the instance context yourself
        • When deriving the instance for (http-api-data-0.2.4:Web.HttpApiData.Internal.ToHttpApiData
                                            (Key Foo))
    
    Main.hs:10:1: error:
        • No instance for (http-api-data-0.2.4:Web.HttpApiData.Internal.FromHttpApiData
                             Bug)
            arising from the 'deriving' clause of a data type declaration
          Possible fix:
            use a standalone 'deriving instance' declaration,
              so you can specify the instance context yourself
        • When deriving the instance for (http-api-data-0.2.4:Web.HttpApiData.Internal.FromHttpApiData
                                            (Key Foo))
    
    Main.hs:10:1: error:
        • No instance for (aeson-0.11.2.1:Data.Aeson.Types.Class.ToJSON
                             Bug)
            arising from the 'deriving' clause of a data type declaration
          Possible fix:
            use a standalone 'deriving instance' declaration,
              so you can specify the instance context yourself
        • When deriving the instance for (aeson-0.11.2.1:Data.Aeson.Types.Class.ToJSON
                                            (Key Foo))
    
    Main.hs:10:1: error:
        • No instance for (aeson-0.11.2.1:Data.Aeson.Types.Class.FromJSON
                             Bug)
            arising from the 'deriving' clause of a data type declaration
          Possible fix:
            use a standalone 'deriving instance' declaration,
              so you can specify the instance context yourself
        • When deriving the instance for (aeson-0.11.2.1:Data.Aeson.Types.Class.FromJSON
                                            (Key Foo))
    

    My problem still stands: I fail to see why these instances are needed, and I feel that the documentation does not address this behaviour of mkPersist.

  2. MHova commented on Feb 27, 2019

    @MHova

    Can any of of the maintainers comment on this?

  3. bitemyapp commented on Feb 27, 2019

    @bitemyapp
    Contributor

    A perusal of the GitHub search results for PathPiece and http-api-data yielded:

    I took a look at persistent-template's source and found:

    -- @'PathPiece'@, @'ToHttpApiData'@ and @'FromHttpApiData'@ instances are only generated for a Key with one field
    

    For mkKeyTypeDec.

    I only see it generating code for the BackendKey. It makes intuitive sense to me that I'd want my BackendKey to have a PathPiece instance, I'm highly likely to use it in a URL.

  4. parsonsmatt commented on Feb 14, 2020

    @parsonsmatt
    Collaborator

    We should be able to remove these requirements soon. #990 added a facility to make deriving instances uniformly easy, so we will be able to drop the automatic derivation. This should additionally make the dependency footprint a bit smaller.

  5. gfarrell commented on Feb 17, 2023

    @gfarrell

    I just encountered this when using persistent to create a schema using the TH functionality, and am quite confused as to why I have to derive or write ToHttpApiData, FromHttpApiData, PathPiece, ToJSON, and FromJSON instances when building a database schema. I don't use yesod, and I sort of expected persistent as a database library rather than a web library, to be well decoupled from it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions