nikita-volkov / refined

Refinement types with static checking
http://hackage.haskell.org/package/refined
MIT License
183 stars 31 forks source link

Build failure with transformers-0.5.6.2 #33

Closed snoyberg closed 5 years ago

snoyberg commented 5 years ago
Building library for refined-0.3.0.0..
[1 of 5] Compiling Refined.These    ( library/Refined/These.hs, dist/build/Refined/These.o )
[2 of 5] Compiling Refined.Internal ( library/Refined/Internal.hs, dist/build/Refined/Internal.o )

library/Refined/Internal.hs:786:29: error:
    • Couldn't match representation of type ‘Identity
                                               (Either RefineException a)’
                               with that of ‘m0 (Either RefineException a)’
        arising from a use of ‘coerce’
      The data constructor ‘Data.Functor.Identity.Identity’
        of newtype ‘Identity’ is not in scope
    • In the second argument of ‘(.>)’, namely ‘coerce’
      In the expression: ExceptT.except .> coerce
      In an equation for ‘refineM’: refineM = ExceptT.except .> coerce
    • Relevant bindings include
        refineM :: Either RefineException a -> RefineM a
          (bound at library/Refined/Internal.hs:786:1)
    |
786 | refineM = ExceptT.except .> coerce
    |        
chessai commented 5 years ago

Sorry for the delay, I've had an extremely busy Q1.

This is strange. Is that constructor no longer in scope? Minour version releases shouldn't cause breakage like that.

snoyberg commented 5 years ago

I'm not familiar with the changes in transformers, but it does seem like this was a breaking change.

brandonhamilton commented 5 years ago

The change made to transformers was to generalize the except function:

- except :: Either e a -> Except e a
- except m = ExceptT (Identity m)

+ except :: (Monad m) => Either e a -> ExceptT e m a
+ except m = ExceptT (return m)

which breaks the usage of coerce in

refineM :: Either RefineException a -> RefineM a
refineM = ExceptT.except .> coerce

Using visible type application fixes this with the new version:

refineM :: Either RefineException a -> RefineM a
refineM = ExceptT.except @Identity .> coerce

I'm not sure what the best way to implement this would be so that it works with both the old and newer versions of the transformers package.

chessai commented 5 years ago

I just added an explicit type signature to coerce: coerce :: ExceptT RefineException Identity a -> RefineM a, and checked that it built with the newest transformers as well as previous versions.