Reputation: 13677
I want to define a generic composition which works both for a -> b
and for a -> Maybe b
:
class Comp m where
(...) :: m a b -> m b c -> m a c
instance Comp (->) where
(...) = (>>>)
instance Comp (a -> Maybe b) where
(...) = (>=>)
Is it possible with all recent GHC extensions to define the second instance without a newtype
wrapper similar to Control.Arrow.Kleisli
?
Another problem is that the instances overlap, so for Just ... Just
two equally sensible instances are possible. Is it possible to redesign ...
so Just ... Just
has polymorphic type so both a -> Maybe (Maybe a)
and a -> Maybe a
are valid typings for it?
If it's not possible maybe it's possible to defer implementation selection somehow. E.g.
data Comp a b = Comp a b
(...) = Comp
($$$) =
($$$)
lifts generic compositions (which can be anything - not necessarily functions) to functions. Then Just ... Just $$$ (fromJust . fromJust)
Upvotes: 3
Views: 151
Reputation: 1335
This is probably not what you are looking for, but it will allow the instances to be defined. Explicit type annotations will often be required to select the appropriate instance. Using your example, Just ... Just
is typed as Comp (->) a (Maybe a) b (Maybe b) => a -> Maybe b
. FunctionalDependencies
might help on cutting down when explicit type annotations are required, but would also restrict the possible instances to less than what you would like.
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Category
import Control.Monad
class Comp m a b b' c where
(...) :: m a b -> m b' c -> m a c
instance Comp (->) a b b c where
(...) = (>>>)
instance Monad m => Comp (->) a (m b) b (m c) where
(...) = (>=>)
Upvotes: 1