hmap :: Generic opaque => (a -> b) -> <opaque container containing a's> -> <same container, but a replaced by b>
hmap @Int show (Either (Just 2) Nothing))
Couldn't such a function be made possible via Generics? /cc @TheMatten
@Reed Mullanix I think getting something to generate terms for you is more or less an orthogonal problem to the one of typeclasses not being first class. Type directed term generation is useful in contexts outside of typeclass dictionaries, and first class typeclass dictionaries are useful in contexts where they can't be generated from the types. There is a big overlap, but I think forcing one thing to be tied to another limits the utility of the resulting solution for both use cases
Functor
won't work, but I'm looking for something that is more ... general than functor? Basically:Does such a thing already exist?
All of these are just
Functor
it's just a pain in the ass in Haskell to witness this
Functor
What I want:
If you
fmap
on Either, it is going to print:Either [Maybe 2] "Maybe 3"
These are all Functors but not
Functor
if that makes senseSure. How do I make it work in Haskell without having to write fmap snakes for each types?
Here is a number of newtypes:
all of these have
Functor
instances given suitable constraintsYou gotta either scrap them typeclasses or pile up the newtypes
Hmm
It's a pain :(
all of your hmaps come down to applying a bunch of tedious newtypes, then using
fmap
, then removing all the newtypesApplyingVia
would be amazing hereMore generally,
ApplyingVia
would be amazingwell not "amazing", but light years ahead of all the manual newtypes
This would be nice:
Couldn't such a function be made possible via
Generics
? /cc @TheMattenPersonally I think ApplyingVia would just be another kludge on a big tower of kludges
Well, yes
SYTC does have it's own problems, even though it is better in quite a few ways
Instead of a newtype explosion you can have these really long chains of functions manipulating records when things could just "work"
@Sridhar Ratnakumar you can write that function sortaaaaaaaaa
The thing about functional programming is that it's about programming with long chains of functions
that's sort of its specialty
so you can always factor them out or import them from libraries or build them up in convenient ways
Really what you need is some sort of type-directed term generation tool... :thinking:
A set of tactics if you will
i wrote a janky ass generic bitraversable instance the other day
one that does exactly this thing you want, srid
but it's disgusting as all hell https://github.com/isovector/hs2/blob/master/hs2-types/src/Hs2/Types/Loc.hs#L50-L138
@Sridhar Ratnakumar
<opaque container containing a>
s isFunctor
BTW, @Asad Saeeduddin https://agda.readthedocs.io/en/v2.6.1/language/implicit-arguments.html?highlight=tactics#tactic-arguments might interest you as a point in the design space
The actual implementation is very rough, but the idea is super solid IMO
@Reed Mullanix I think getting something to generate terms for you is more or less an orthogonal problem to the one of typeclasses not being first class. Type directed term generation is useful in contexts outside of typeclass dictionaries, and first class typeclass dictionaries are useful in contexts where they can't be generated from the types. There is a big overlap, but I think forcing one thing to be tied to another limits the utility of the resulting solution for both use cases
I'll check it out, thanks
To clarify, I am 100% on board with 1st class dictionaries, to the point of getting rid of typeclasses altogether and just using implicits
The only reason people use typeclasses is for the automatic instance search, so if you add that, may as well make it programmable!
well apart from the "automatic instance search", there's also the "single instance" thing :(
That is just a constraint on the search though!
for
Set
s andMap
s you would want it to be activebut not for
Monoid
sis this explored somewhere?
@Sridhar Ratnakumar another solution is this https://wiki.haskell.org/Scrap_your_boilerplate#fmap
(of note: yes, it is explored - this is exactly what instance arguments are in agda)