retrie icon indicating copy to clipboard operation
retrie copied to clipboard

Rewriting to add constraints?

Open isovector opened this issue 4 years ago • 6 comments
trafficstars

Hi all,

I've got a big refactoring project coming up, and am wondering if retrie can help me. I'd like to change the following signature:

foo :: Sem r ()

to instead be:

foo :: Member (Embed IO) r => Sem r ()

and then push the Member (Embed IO) r constraint through all transitive callsites to foo. None of the documentation seems to suggests anything about this use case --- can retrie handle it?

isovector avatar Sep 01 '21 16:09 isovector

That would be sweet, but I don't think retrie is able to rewrite types.

EDIT: I was wrong, see --adhoc-type

pepeiborra avatar Sep 01 '21 17:09 pepeiborra

You can hack something that traverses the hie file, looking for occurrences of foo with the type Sem r () and then uses SYB + ghc-exactprint to rewrite it.

processFile :: DynFlags -> HieFile -> IO ()
processFile dflags HieFile{..} =
  forM_ (getAsts hie_asts) $ \root ->
    forM_ (flattenAst root) $ \Node{..} -> do
      let NodeInfo{..} = nodeInfo
      case Map.toList nodeIdentifiers of
        [(Right name, IdentifierDetails{..})]
          | (ty:_) <- nodeType
          , Just _ <- identType
          , [Use] <- Set.toList identInfo ->
             processName dflags nodeSpan name $ recoverFullType ty hie_types
        _ -> return ()

processName :: DynFlags -> Span -> Name -> HieTypeFix -> IO ()
processName dflags loc name ty = ... pattern match and use SYB and ghc-exactprint ...

I wonder if this could be generalised and incorporated in retrie somehow

pepeiborra avatar Sep 02 '21 08:09 pepeiborra

Would such a thing do transitive dependencies? Like, anything that calls anything that calls foo also needs an updated type signature.

I think I'll probably just play whack-a-mole in HLS on this one. Add constraint is pretty fantastic!

isovector avatar Sep 02 '21 13:09 isovector

Without touching the callsite, would it be possible to use retrie for changing:

bar :: a -> IO b

... into:

bar :: MonadIO m => a -> m b

It seems like retrie --adhoc-type 'IO b = MonadIO m => m b' produces bar :: a -> (MonadIO m => m b) but a -> IO b = MonadIO m => a -> m b fails with Malformed head of type or class declaration: a -> IO b or Fn a (IO b) = ... fails with Unexpected type ‘IO b’.

Am I missing something, or is it currently not possible to add contraints on multi argument function?

TristanCacqueray avatar Oct 05 '21 15:10 TristanCacqueray

Can you run a second adhoc-type rewrite to fix the malformed signatures? --adhoc-type 'a -> (MonadIO m => m b) = MonadIO m => a -> m b

pepeiborra avatar Oct 06 '21 10:10 pepeiborra

@pepeiborra unfortunately this fails with this message:

["type a -> (MonadIO m => m b) = MonadIO m => a -> m b"]

parseAdhocTypes:1:6: error:
    Malformed head of type or class declaration: a -> (MonadIO m => m b)
retrie: user error (parse failed)

Similarly, trying Fn a (MonadIO m => m b) = ... results in Unexpected type ‘MonadIO m => m b’

TristanCacqueray avatar Oct 06 '21 12:10 TristanCacqueray