3 ms·
> The result is a type focusing on callback transformation: > type BIO inp out = (Maybe out -> IO ()) -> Maybe inp -> IO () Huh, neat! Looks like profunctor o
by Twisol 5y ago
> The result is a type focusing on callback transformation:
> type BIO inp out = (Maybe out -> IO ()) -> Maybe inp -> IO ()
Huh, neat! Looks like profunctor optics to me. ("Callback transformation" is a really good way to think about profunctor optics, honestly. The "profunctor" part describes the kind of callback you're transforming.)
Generalize slightly:
type (:>>:) s t = Maybe s -> IO t
type BIO' s t a b = (s :>>: t) -> (a :>>: b)
type BIO inp out = BIO' out () inp ()
Tweaked just a bit further, to highlight the similarity with general profunctor optics:
type BIO' s t a b = (Profunctor p, p ~ (:>>:)) => p s t -> p a b
That is, BIO' is the type of optics that only work specifically for the profunctor :>>:. (As it happens, `f a -> g b` is a profunctor for any pair of functors `f` and `g`.)
With either representation, you should be able to compose BIO transformations with general prisms and get BIO transformations back. (Lenses are out; I don't think you can implement `Strong` for `:>>:`.)
instance Choice (:>>:) where
-- left' :: (Maybe a -> IO b) -> (Maybe (Either a c) -> IO (Either b c))
left' :: (a :>>: b) -> ((Either a c) :>>: (Either b c))
left' f Nothing = fmap Left (f Nothing)
left' f (Just (Left a)) = fmap Left (f (Just a))
left' f (Just (Right c)) = fmap Right (return c)