Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optic for partial conversion on both sides

Prism is like Iso except one of the two conversions is partial. Is there an optic where both conversions are partial?

Of course one can create a type (s -> Maybe a, b -> Maybe t) but I'm wondering if such a thing could be expressed an as Optic _ _?

like image 739
yairchu Avatar asked Dec 22 '22 20:12

yairchu


1 Answers

You can generalize Isos (i.e., (s -> a, b -> t)) into (s -> m a, b -> m t) by replacing profunctors over Hask (i.e., Profunctor, that's the constraint in the definition of Iso as an Optic) with profunctors over Kleisli categories (here for the Maybe monad).

class Monad m => KProfunctor m p where
  dimapM :: (s -> m a) -> (b -> m t) -> p a b -> p s t

-- dimapM pure pure = id
-- dimapM f g . dimapM h i = dimapM (h >=> f) (g >=> i)

type Optic p s t a b = p a b -> p s t
type KIso m s t a b = forall p. KProfunctor m p => Optic p s t a b

To construct one example of such profunctor, take the type of pseudo-isos (s -> m a, b -> m t) that we are trying to work with in the first place, and put s and t as the main indices:

data PseudoIso m a b s t = MkPseudoIso
  { toM :: s -> m a
  , fromM :: b -> m t
  }

instance Monad m => KProfunctor m (PseudoIso m) where
  -- exercise for the reader
  • To go from PseudoIso to KIso, use dimapM (the fields of PseudoIso are exactly the right type for the arguments of dimapM)
  • To go from KIso to PseudoIso, partially apply to the identity PseudoIso a b a b

Actually, it doesn't have to be a Kleisli category. A profunctor over any category (:->) :: k -> k -> Type will give you a class of optics of the form (s :-> a, b :-> t).

Note: you can define an instance of Choice with KProfunctor Maybe, so maybe everything should really be specialized to Maybe so Choice could reasonably be added as a superclass of KProfunctor, then KIso would be a subtype of Prism.

like image 187
Li-yao Xia Avatar answered Dec 25 '22 08:12

Li-yao Xia