Is it possible to get all contexts of a Traversable lazily?

后端 未结 4 1786
一向
一向 2021-02-07 02:56

lens offers holesOf, which is a somewhat more general and powerful version of this hypothetical function:

holesList :: Traversable t
          =>         


        
4条回答
  •  暖寄归人
    2021-02-07 03:47

    This doesn't really answer the original question, but it shows another angle. It looks like this question is actually tied rather deeply to a previous question I asked. Suppose that Traversable had an additional method:

    traverse2 :: Biapplicative f
               => (a -> f b c) -> t a -> f (t b) (t c)
    

    Note: This method can actually be implemented legitimately for any concrete Traversable datatype. For oddities like

    newtype T a = T (forall f b. Applicative f => (a -> f b) -> f (T b))
    

    see the illegitimate ways in the answers to the linked question.

    With that in place, we can design a type very similar to Roman's, but with a twist from rampion's:

    newtype Holes t m x = Holes { runHoles :: (x -> t) -> (m, x) }
    
    instance Bifunctor (Holes t) where
      bimap f g xs = Holes $ \xt ->
        let
          (qf, qv) = runHoles xs (xt . g)
        in (f qf, g qv)
    
    instance Biapplicative (Holes t) where
      bipure x y = Holes $ \_ -> (x, y)
      fs <<*>> xs = Holes $ \xt ->
        let
          (pf, pv) = runHoles fs (\cd -> xt (cd qv))
          (qf, qv) = runHoles xs (\c -> xt (pv c))
        in (pf qf, pv qv)
    

    Now everything is dead simple:

    holedOne :: a -> Holes (t a) (a, a -> t a) a
    holedOne x = Holes $ \xt -> ((x, xt), x)
    
    holed :: Traversable t => t a -> t (a, a -> t a)
    holed xs = fst (runHoles (traverse2 holedOne xs) id)
    

提交回复
热议问题