Quick actions

cmd+k|ctrl+k

Navigation

Languages

Generic coyoneda

Snippet info

Language

Haskell

Visibility

public

Author

rightfold

Created

2018-11-28T18:15:05Z

Updated

2018-11-29T09:43:29Z

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Main
  ( main
  ) where

import Prelude hiding ((.), id)

import Control.Arrow (Kleisli (..))
import Control.Category (Category, (.), id)
import Data.Profunctor (Profunctor, rmap)

-- From Control.Categorical.Functor.
class (Category r, Category t) => GFunctor f r t | f r -> t, f t -> r where
  gfmap :: r a b -> t (f a) (f b)

--------------------------------------------------------------------------------

data Coyoneda p f a where
  Coyoneda :: p a b -> f a -> Coyoneda p f b

instance Profunctor p => Functor (Coyoneda p f) where
  fmap f (Coyoneda g a) = Coyoneda (rmap f g) a

instance Category p => GFunctor (Coyoneda p f) p (->) where
  gfmap f (Coyoneda g a) = Coyoneda (f . g) a

liftCoyoneda :: Category p => f a -> Coyoneda p f a
liftCoyoneda = Coyoneda id

lowerCoyoneda :: GFunctor f p (->) => Coyoneda p f a -> f a
lowerCoyoneda (Coyoneda f a) = gfmap f a

sequenceCoyoneda :: (Applicative m, Traversable f) => Coyoneda (Kleisli m) f a -> m (f a)
sequenceCoyoneda (Coyoneda f a) = traverse (runKleisli f) a

--------------------------------------------------------------------------------

prompt :: String -> IO String
prompt m = putStr m *> putStr "> " *> getLine

main :: IO ()
main = example1 *> example2

example1 :: IO ()
example1 =
  let foo = liftCoyoneda ["A"] in
  let bar = gfmap (Kleisli prompt) foo in
  let baz = gfmap (Kleisli prompt) bar in
  print =<< sequenceCoyoneda baz

example2 :: IO ()
example2 =
  let foo = ["A"] in
  let bar = traverse prompt foo in
  let baz = traverse prompt =<< bar in
  print =<< baz
INFO