fission-codes / fission

Fission CLI & server
https://runfission.com/docs
119 stars 14 forks source link

Upgrade hs-ucan to spec v0.8.2 #588

Closed matheus23 closed 2 years ago

matheus23 commented 2 years ago

These are breaking hs-ucan v0.7 changes right now. The tests are messy, but it happily reads ts-ucan v0.7 UCANs and computes their capability scope.

This is a draft, because I'm in the process of upgrading to UCAN v0.8.1. I figured this is interesting nonetheless.

The base of this branch is ucan-upgrade, not main, because I'm solely working in hs-ucan/ for now, and leave the rest of the monorepo in a non-compiling state.

matheus23 commented 2 years ago

Ok, sorry for the notification & PR spam @expede, but this is finally the "correct" diff for this PR.

matheus23 commented 2 years ago

Remaining things to-do:

Explicitly not to do today is rights amplification, i.e. another function in the DelegationSemantics type class & another delegation type in the Proof data type in Capabilities.hs.

matheus23 commented 2 years ago

How do you like that @expede? :D

https://github.com/fission-suite/fission/blob/0f6a41a8d76a6c5ed147e67e7a274cee218ee1f9/hs-ucan/library/Web/UCAN/DelegationChain/Class.hs#L16-L22

Usage in the delegation chain algorithms (much less indentation!): https://github.com/fission-suite/fission/blob/0f6a41a8d76a6c5ed147e67e7a274cee218ee1f9/hs-ucan/library/Web/UCAN/DelegationChain.hs#L141-L160

Thanks for pushing me to do that thing. Much better now I think.

matheus23 commented 2 years ago

Turns out not that much! Brooke gave me great feedback. I'm prouder of this version now:

-- | A monad abstracting over iterating elements
class Alternative m => MonadWalk m where
  walk :: Foldable f => f a -> m a

newtype StreamWithErrors m a
  = StreamWithErrors { runStreamWithErrors :: ListT m (Either Error a) }
  deriving Functor

instance Monad m => MonadWalk (StreamWithErrors m) where
  walk = StreamWithErrors . fmap Right . ListT.fromFoldable

instance Monad m => MonadError Error (StreamWithErrors m) where
  throwError = StreamWithErrors . return . Left
  catchError (StreamWithErrors listt) handler =
    StreamWithErrors $ do
      listt >>= \case
        Right a  -> return $ Right a
        Left err -> runStreamWithErrors $ handler err

Essentially, I've split up the MonadDelegationChain into MonadWalk and MonadError Error.

Much nicer now! Also, I feel like MonadWalk must exist out there already, but I can't find it! Anyway. :man_shrugging:

expede commented 2 years ago

Thanks for pushing me to do that thing. Much better now I think.

You're very welcome! I'm glad it was helpful 😀

Brooke gave me great feedback. I'm prouder of this version now

Oh yeah, this looks awesome 🎉 I love this pattern. This code is super clean, super legible, easy to follow ✨👏👏👏✨

Also, I feel like MonadWalk must exist out there already, but I can't find it!

I haven't actually looked at the implementation in depth, but the description for select sounds maybe related?

Convert any collection that implements Foldable to another collection that implements Alternative

For this library, the most common specialized type for select will be:

select :: [a] -> ListT IO a

select :: (Foldable f, Alternative m) => f a -> m a
select = Data.Foldable.foldr cons empty
  where
    cons x xs = pure x <|> xs

Despite the name, this looks about right or at least right for an after midnight quick glance 😅😛), especially considering what fromFoldable looks like:

fromFoldable :: (Monad m, Foldable f) => f a -> ListT m a
fromFoldable = foldr cons mzero

That said, I think that the custom typeclass is super expressive to read, so I wouldn't change anything

matheus23 commented 2 years ago

Ooooh right. You don't need a custom type class if select follows from Alternative 🤔

expede commented 2 years ago

You don't need a custom type class if select follows from Alternative 🤔

Unless you want to abstract over the behaviour completely, in which case you'd possibly want to drop some of the constraints in the class to make it more general.

That said, if using Alternative+Foldable suffices here, then 🚀