The linked Haddock is not on Hackage. It’s locally built and manually uploaded by myself. It might go outdated in the future. (I know I should set up CI though…)
I’m particularly interested in how you think about these points I’m uncertain about.
Usefulness. I’m yet to find a substantial use of the type classes in my library, FFunctor or FMonad, in a practical programming task. Should I put it on Hackage despite not knowing the actual value to other users?
Documentation. The current documentation should have many errors and unfriendly explanations. In addition to my English ability, the math-y nature of this library make it hard for me to write good documentation. Any feedback on documentation is double welcome.
Usefulness. I’m yet to find a substantial use of the type classes in my library, FFunctor or FMonad, in a practical programming task. Should I put it on Hackage despite not knowing the actual value to other users?
One package that wasn’t mentioned in the README was hkd: "higher-kinded data", which provides everything you do sans FMonad and a bit more for various SOP manipulations. I can’t speak to whether FMonad would be useful, but I haven’t seen many useful things in the wild that fit that abstraction. I’m interested to see if people have instances lying around that are actually nice to work with. I am a bit invested in this because I abandoned a particular sandbox a while ago (GitHub - emilypi/higher-functors: Higher-order Functors - feel free to crib anything and everything you care about) that was an attempt to see whether the higher order hierarchy was a useful concept in general, and I had to pull back on account of most “useful” things I worked with needing to be (k -> Type) -> Type as opposed to the full (k -> Type) -> k -> Type.
I’m stoked that we came up with the saem type signatures and laws for basically everything tho
Documentation. The current documentation should have many errors and unfriendly explanations. In addition to my English ability, the math-y nature of this library make it hard for me to write good documentation. Any feedback on documentation is double welcome.
They are endofunctors on the category of type constructors of kind k -> Type and polymorphic functions t :: forall (x :: k). f x -> g x.
While any instance of FFunctor from this package can be faithfully represented as a IFunctor, some instances can’t be an instance of IFunctoras is.
Most notably, Free can’t be an instance of IFunctor directly,
because Free needs Functor h to be able to implement fmapI, the method of IFunctor.
class IFunctor ff where
fmapI :: (g ~> h) -> (ff g ~> ff h)
There exists a workaround: you can use another representation of Free f which doesn’t require Functor f to be a Functor itself,
for example Program from operational package.
This package avoids the neccesity of the workaround by admitting the restriction that the parameter of FFunctor must always be a Functor.
Therefore, FFunctor gives up instances which don’t take Functor parameter, for example, a type constructor F with kind F :: (Nat -> Type) -> Nat -> Type.
Saying the same thing quickly, Any FFunctor ff can be encoded as IFunctor (ff ∘ Coyoneda). Many instances can have a more direct IFunctor ff instance, but some (like Free) can’t avoid the Coyoneda indirection.
My another justification of being less general is that a library focusing on a specific structure in detail is no worse than a library for generic things. Anyway, I think the “correct” direction for the ultimate generalization is to have the functor class between arbitrary categories (or higher-categories or …)
One of that specific detail is, like you said, FStrong ff. It makes sense only for a FFunctor ff. Not just because of its kind, but also for the fact Day f g makes sense only for Functor f and Functor g. A hypothetical “take-Functor-and-return-Contravariant-functor” with kind (Type -> Type) -> Type -> Type can well be IFunctor but it wants another class using other tensor products, not FStrong.
Or I’m just getting too fixated on the first idea I got.
This looks interesting, but I don’t see the decisive advantage over mmorph yet. Maybe look for common usage patterns of mmorph and try to translate them to situations where your functor is not a monad. Although you’d have to prove then that mmorph is not applicable in these situations.
Yes, why not? It increases discoverability, and might eventually lead someone with a use case to your library.
I find your documentation great for a new package, and wish that other libraries also had this quality of documentation. For example, the tables comparing Functor vs. FFunctor and similar are great.