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

Can no longer derive ParseTime instance #119

Closed
jonschoning opened this issue Oct 12, 2019 · 7 comments
Closed

Can no longer derive ParseTime instance #119

jonschoning opened this issue Oct 12, 2019 · 7 comments
Assignees
Milestone

Comments

@jonschoning
Copy link

I upgraded from time-1.8.0.2 to time-1.9.3, and found this causes some code that was working with time-1.8.0.2 to break when deriving an instance for ParseTime.

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.Time as TI
newtype DateTime = DateTime { unDateTime :: TI.UTCTime }
  deriving (TI.ParseTime,TI.FormatTime)
    • Couldn't match representation of type ‘proxy TI.UTCTime’
                               with that of ‘proxy DateTime’
        arising from the coercion of the method ‘time-1.9.3:Data.Time.Format.Parse.Class.parseTimeSpecifier’
          from type ‘forall (proxy :: * -> *).
                     proxy TI.UTCTime
                     -> TI.TimeLocale
                     -> Maybe
                          time-1.9.3:Data.Time.Format.Parse.Class.ParseNumericPadding
                     -> Char
                     -> Text.ParserCombinators.ReadP.ReadP String’
            to type ‘forall (proxy :: * -> *).
                     proxy DateTime
                     -> TI.TimeLocale
                     -> Maybe
                          time-1.9.3:Data.Time.Format.Parse.Class.ParseNumericPadding
                     -> Char
                     -> Text.ParserCombinators.ReadP.ReadP String’
      NB: We cannot know what roles the parameters to ‘proxy’ have;
        we must assume that the role is nominal
    • When deriving the instance for (TI.ParseTime DateTime)
    |
423 |   deriving (TI.ParseTime,TI.FormatTime)
    |             ^^^^^^^^^^^^

i mentioned this to someone how i could work around this and they said

You'd need to unfortunately alter the class definition to guarantee that the proxy has a representational role and not nominal

or alternatively,

a patch to time to use this https://hackage.haskell.org/package/coerce-role on the proxy type variable would probably do the trick

@AshleyYakeley
Copy link
Member

I hadn't really intended to allow people to create their own instances of FormatTime or ParseTime, as the definitions of those classes might change. Though I suppose I could allow newtype-deriving.

Does it help to import Data.Time.Format.Internal? This exposes those classes in full.

@jonschoning
Copy link
Author

jonschoning commented Oct 12, 2019

yes, I'm not able to derive ParseTime as before, but by importing Data.Time.Format.Internal it looks like i'm able to manually derive an instance e.g.

instance TI.ParseTime DateTime where
  parseTimeSpecifier _ = TI.parseTimeSpecifier (P.Proxy :: P.Proxy TI.UTCTime)
  buildTime l xs = DateTime <$> TI.buildTime l xs

although this relies on internals that you mentioned might change.

@AshleyYakeley
Copy link
Member

Well, that's not ideal. I think newtype-deriving should work.

Probably the simplest thing would be to replace the proxy type parameters with the Proxy type, which is known to have a representational (actually, phantom) role in its argument.

@AshleyYakeley
Copy link
Member

Fixed for 1.10

@thomasjm
Copy link

@AshleyYakeley thanks for fixing this! Is there an ETA for a release of 1.10 on Hackage (or even better, Stackage?)

Context: I'm trying to build https://github.com/kubernetes-client/haskell on the new GHC 8.8 and running into this issue.

@AshleyYakeley
Copy link
Member

@thomasjm 1.10 is now up on Hackage.

Stackage policy is to keep core library versions matched with the ones in GHC, so it won't be in Stackage until it's first in GHC (probably 8.10) and then there's a new LTS for that version of GHC. In the mean time, however, you can add time-1.10 to your extra-deps.

@thomasjm
Copy link

It turns out the instance you mentioned @jonschoning actually does not work properly. I introduced it to a OpenAPI-generated library so that I could build against the latest time, and it compiled okay, but it actually failed to parse time strings.

I'm working with the Kubernetes library, and found it failed to parse a string like "2020-08-12T03:39:54Z". The K8S comments refer to this as an RFC3339 time string.

Not sure why this happens. However, it doesn't seem necessary to actually derive a ParseTime instance for the newtype. I fixed the problem by parsing the underlying UTCTime directly and then wrapping it in the newtype. In case it helps anyone else, you can see what I did here: https://github.com/codedownio/haskell/commit/685903376751d081fa0e11e9ea4c41277c6cf9f8

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

3 participants