-
Notifications
You must be signed in to change notification settings - Fork 87
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
Class-based algebras. #13
base: master
Are you sure you want to change the base?
Conversation
Current coverage is
|
def apply(v1: E[F[G[A]]]) = f(v1) | ||
} | ||
object GElgotAlgebraM { | ||
implicit def zip[E[_]: Functor, G[_]: Functor, M[_]: Applicative, F[_]: Functor]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is the potential here for zip
to get shadowed by a local definition since it's such a common identifier, so it might make sense to call this method gElgotAlgebraMZip
or similar.
On further inspection maybe this was intentional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not intentional as such … but I have never managed to have this implicit found, so I always have to explicitly refer to GElgotAlgebraM.zip.zip
, with some type parameters thrown in to get it to work. So the short name seemed useful.
I would be happy to give it a long name if it means that implicit search will find it, but no luck so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also add zip
as a method on GElgotAlgebraM
(and then just delegate to it here) which would eliminate the need to explicitly refer to this instance when you aren't working abstractly with some F[_]: Zip
.
@@ -312,15 +391,23 @@ package object matryoshka extends CofreeInstances with FreeInstances { | |||
CorecursiveOps[T, F] = | |||
new CorecursiveOps[T, F](f) | |||
|
|||
implicit def ToAlgebraOps[F[_], A](a: Algebra[F, A]): AlgebraOps[F, A] = | |||
new AlgebraOps[F, A](a) | |||
implicit sealed class CofreeOps[F[_], A](self: Cofree[F, A]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could make this and FreeOps
final
classes.
@sellout 👍 (apologies for the delay, I thought I had confirmed this already!). |
@sellout So we're approaching the first anniversary of this PR, not sure if that makes it easier or harder to close ;) |
Hah, yes – I was about to go over this and the even older PR that’s still open. See if there’s anything worth salvaging – at least open some issues. |
I would love to see class based algebras, including composable Bialgebras (and Bimonads) as first-class entities. I think the smart move would be to reduce the function and concept footprint of the current library and create multiple ways to assemble the arguments to a smaller number of functions. A tiny handful of morphisms dominate all uses, and the details of inference and implicits dominate the ergonomics of using the library. If you look at a generalized hylomorphism from different perspectives (input-centric, algebra-centric, monad-centric, adjoint-fold-centric ...) different interfaces emerge. And being explicit about partial application is a tremendous boon for usage because you can lose a lot of the type lambdas and work with single argument type constructors. |
This adds some functionality, but also generalizes things pretty extremely.
I took the approach suggested by @wemrysi and defined a class for the most generic {co}algebras, then used type alias for the more constrained ones. I ended up having to explicitly define a subclass for
GCoalgebra
, because scalac doesn’t likeId[Id[_]]
showing up in types.We now
.attribute
any algebra;.generalize
,.generalizeElgot
, and.generalizeM
any {co}algebra (that doesn’t already have a functor in the generalizing position);transApoM
(for @drostron);GElgot*lgebraM
);I have a couple issues with this – having to explicitly call an implicit conversion in some cases and still not being able to get
.zip
from implicit conversions.Also, there are more changes to be made to make the types consistent. But, in general, algebras implicitly convert to/from functions fine, while coalgebras, maybe not so much.