Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Natural transformation as an argument in Haskell

Tags:

haskell

I'm looking for a way to define natural transformation as a simple argument to pass to a function.

Let's have a simple function as an example:

mapK :: (m Int -> IO Int) -> Kleisli m Bool Int -> Kleisli IO Bool Int
mapK toIO kleisli = Kleisli (\bool -> toIO $ runKleisli kleisli bool)

Neat, but if I change it to:

mapK :: (m a -> IO a) -> Kleisli m Bool Int -> Kleisli IO Bool Int
mapK toIO kleisli = Kleisli (\bool -> toIO $ runKleisli kleisli bool)

I get the error that Int isn't an a (no surprise there).

I know it's possible to achieve it using constraint like:

class NaturalTransformation f g where
  transform :: f a -> g a

mapK :: (NaturalTransformation m IO) => Kleisli m Bool Int -> Kleisli IO Bool Int

but I'm curious if it's also possible to do it in plain arguments.

like image 416
Sergey Kolbasov Avatar asked Mar 03 '23 14:03

Sergey Kolbasov


1 Answers

Certainly, you just need to demand that the implementer, not the caller, gets to choose the variable:

{-# LANGUAGE RankNTypes #-}
mapK :: (forall a. m a -> IO a) -> Kleisli m Bool Int -> Kleisli IO Bool Int
-- implementation is exactly as before
mapK toIO kleisli = Kleisli (toIO . runKleisli kleisli)
-- OR, with TypeApplications also on,
mapK toIO = coerce @(_ (Bool -> _ Int)) (toIO.)
like image 97
Daniel Wagner Avatar answered Mar 13 '23 04:03

Daniel Wagner