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

后端 未结 4 1789
一向
一向 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:44

    Here is an implementation that is short, total (if you ignore the circularity), doesn't use any intermediate data structures, and is lazy (works on any kind of infinite traversable):

    import Control.Applicative
    import Data.Traversable
    
    holes :: Traversable t => t a -> t (a, a -> t a)
    holes t = flip runKA id $ for t $ \a ->
      KA $ \k ->
        let f a' = fst <$> k (a', f)
        in (a, f)
    
    newtype KA r a = KA { runKA :: (a -> r) -> a }
    
    instance Functor (KA r) where fmap f a = pure f <*> a
    instance Applicative (KA r) where
      pure a = KA (\_ -> a)
      liftA2 f (KA ka) (KA kb) = KA $ \cr ->
        let
          a = ka ar
          b = kb br
          ar a' = cr $ f a' b
          br b' = cr $ f a b'
        in f a b
    

    KA is a "lazy continuation applicative functor". If we replace it with the standard Cont monad, we also get a working solution, which is not lazy, however:

    import Control.Monad.Cont
    import Data.Traversable
    
    holes :: Traversable t => t a -> t (a, a -> t a)
    holes t = flip runCont id $ for t $ \a ->
      cont $ \k ->
        let f a' = fst <$> k (a', f)
        in k (a, f)
    

提交回复
热议问题