ekmett / profunctors

Haskell 98 Profunctors
http://hackage.haskell.org/package/profunctors
Other
70 stars 43 forks source link

Add roam method to `Mapping` #50

Closed treeowl closed 6 years ago

treeowl commented 7 years ago

I don't know if this is useful or not, but Mapping supports a roam method similar to wander.

treeowl commented 7 years ago

Urk. I hate how Github note things work. It would be much, much nicer to use Representable here than Distributive and Applicative, but that would incur an adjunctions dependency. We need the Applicative to implement wanderMapping and for several of the Mapping instances. If we had Representable instead of Distributive, I think we could use Data.Functor.Rep.Co to get everything we need.

treeowl commented 7 years ago

Trying to pin down the representable functor to a function doesn't seem to work too well; things that can be coercions end up not. So I guess (Distributive f, Applicative f) may be the way to go for now, sad as it is.

phadej commented 7 years ago

Is there some adjunction-like interaction happening between

phadej commented 7 years ago

FWIW: Settable has also Traversable. I guess it's is trivially satisfied by any Representable functor.

treeowl commented 7 years ago

I don't know any of this theory, really. Anything Distributive should also support a Representable instance (unique, but sadly only up to isomorphism). Using that allows more functions to be passed to roam (the payoff). It also, I believe, simplifies the Kleisli and Star instance constraints to eliminate the Applicative and Monad components. We keep tacking constraints onto Distributive because (I think) we really want Representable.

The trouble with Representable, in some contexts, is that we need to expose a representation type as part of the API. I wonder if there's some way around that using TypeInType

phadej commented 7 years ago

And for usefulness: In profunctor based optics Representable definition is simpler, as then one can define setting, otherwise we need to stick with collecting only (or use p ~ (->) constraint which I don't like).

type Setter s t a b = forall p. Mapping p => Optic p s t a b
type Optic p s t a b = p a b -> p s t

-- I don't see easy way to define without `Distributive` and `Applicative` only
setting :: ((a -> b) -> s -> t) -> Setter s t a b
setting f = roam $ \g s -> tabulate $ \idx ->
    f (flip index idx . g) s

-- Distributive and Applicative constraint would be enough, if one don't need `setting`
collecting
    :: (forall f. Representable f => (a -> f b) -> s -> f t)
    -> Setter s t a b
collecting = roam

EDIT:

And because we have Representable f, using Star f, we can over many inputs at once: (it's not collectOf, as that won't allow traverse' to be there).

>>> overMany (mapped . traverse') (\i -> V2 (negate i) i) [[1,2],[3]]
V2 [[-1,-2],[-3]] [[1,2],[3]]