Skip to content
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

Indexed alternative/alignable instance for proxies #220

Open
masaeedu opened this issue May 21, 2020 · 3 comments
Open

Indexed alternative/alignable instance for proxies #220

masaeedu opened this issue May 21, 2020 · 3 comments

Comments

@masaeedu
Copy link

masaeedu commented May 21, 2020

In #218 I suggested that "balanced" pipes form an indexed applicative, which in other words is a particular kind of lax monoidal functor:

class Functor f => EssenceOfApply f
  where
  zip :: (f a, f b) -> f (a, b)

But there are other sorts of monoidal functors. For example there is Alternative:

class Functor f => EssenceOfAlt f
  where
  union :: (f a, f b) -> f (Either a b)

and Alignable:

class Functor f => EssenceOfAlign f
  where
  align :: (f a, f b) -> f (These a b)

While the additional restrictions involved in balancing the shared interface are necessary to equip Proxy with an indexed applicative structure, it seems we don't have any such restrictions for an indexed alternative or indexed align:

data Proxy a' a b' b m r
  where
  Fin :: r                                -> Proxy a' a b' b m r
  Res :: (b' -> (b, Proxy a' a b' b m r)) -> Proxy a' a b' b m r
  Req :: a' -> (a -> Proxy a' a b' b m r) -> Proxy a' a b' b m r
  Eff :: m (Proxy a' a b' b m r)          -> Proxy a' a b' b m r

deriving instance Functor m => Functor (Proxy a' a b' b m)

data These a b = This a | That b | These a b

these :: (a -> b -> c) -> (a -> c) -> (b -> c) -> These a b -> c
these f _ _ (These a b) = f a b
these _ f _ (This a) = f a
these _ _ f (That a) = f a

align :: Functor m =>
  Proxy b' b c' c m r ->
  Proxy a' a b' b m s ->
  Proxy a' a c' c m (These r s)
Fin r   `align` Fin s   = Fin $ These r s

Fin r   `align` _       = Fin $ This r
_       `align` Fin r   = Fin $ That r

Res f   `align` y       = Res $ fmap (`align` y) . f
x       `align` Req y f = Req y $ (x `align`) . f

Eff m   `align` y       = Eff $ (`align` y) <$> m
x       `align` Eff m   = Eff $ (x `align`) <$> m

Req r f `align` Res g   = let (b, v) = g r in f b `align` v

union :: Functor m =>
  Proxy b' b c' c m r ->
  Proxy a' a b' b m s ->
  Proxy a' a b' b m (Either r s)
union x y = (these (\x _ -> Left x) Left Right) align x y

I haven't thought too hard about whether the associativity law works out here, but I feel like it should. The other problem is: what (if anything) is the identity? It seems to me that an "infinite" proxy that never returns would act as the identity for union, since the overall result is the one of the shorter proxy:

empty :: Applicative m => Proxy a' a b' b m v
empty = Eff $ pure $ empty

Not sure whether any of the above is right, but I thought I'd share the idea at least.

@Gabriella439
Copy link
Owner

@masaeedu: I believe the identity of union would be cat (treating Either Void a as isomorphic to a)

I also think the identity of align would be something like Pipes.take n, where n would be the index used to track how the number of requests/responses at the interface

@masaeedu
Copy link
Author

masaeedu commented May 28, 2020

@Gabriel439 Wouldn't cat :: Monad m => Proxy () a () a m r have the wrong type? We need something of type Proxy a' a a' a m Void.

The second () I just realized we can deal with, because it's in a contravariant position. So for that one we can just map in a discard :: x -> () and get contramapSomewhere discard $ cat :: Monad m => Proxy () a a' a m r. The first () is in a covariant position though, so I don't think we can get rid of it.

@Gabriella439
Copy link
Owner

@masaeedu: Oh yeah, you're right! Never mind 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants