I've been trying to write a custom Optics data structure that generalises Lenses, Prisms and Traversals. My data structure looks like this:
data Optic m a b = Optic { view :: a -> m b
, over :: a -> (b -> b) -> a
}
I want to write a function that composes two Optics, optic1 :: Optic m a b and optic2 :: Optic n b c to produce an Optic containing view :: a -> m (n c) and over :: a -> (c -> c) -> a.
In my head, the type of this composed Optic would be Optic (m n) a c, but this doesn't work - GHC will complain that m has one too many type arguments and n one too few.
Here's my non-compiling implementation of the compose function:
compose :: Optic m a b -> Optic n b c -> (m b -> (b -> n c) -> m (n c)) -> Optic (m n) a c
compose optic1 optic2 glue = Optic { view = viewCompose (view optic1) (view optic2) glue
, over = overCompose (over optic1) (over optic2)
}
viewCompose :: (a -> m b) -> (b -> n c) -> (m b -> (b -> n c) -> m (n c)) -> a -> m (n c)
viewCompose view1 view2 glue x = glue (view1 x) view2
overCompose :: (a -> (b -> b) -> a) -> (b -> (c -> c) -> b) -> a -> (c -> c) -> a
overCompose over1 over2 x f = over1 x (\y -> over2 y f)
The GHC error messages are:
optic.hs:7:83: error:
• Expecting one fewer argument to ‘m n’
Expected kind ‘* -> *’, but ‘m n’ has kind ‘*’
• In the first argument of ‘Optic’, namely ‘m n’
In the type signature:
compose :: Optic m a b
-> Optic n b c -> (m b -> (b -> n c) -> m (n c)) -> Optic (m n) a c
optic.hs:7:85: error:
• Expecting one more argument to ‘n’
Expected a type, but ‘n’ has kind ‘* -> *’
• In the first argument of ‘m’, namely ‘n’
In the first argument of ‘Optic’, namely ‘m n’
In the type signature:
compose :: Optic m a b
-> Optic n b c -> (m b -> (b -> n c) -> m (n c)) -> Optic (m n) a c
If I create an optic of type Optic Maybe Int Int, GHC understands that the first type argument has kind * -> * and doesn't complain about insufficient arguments. But I can't figure out how to combine types together to create another type of kind * -> *.
Is there any way (with or without language extensions) to express something like:
Optic (forall t. m (n t)) a c