I had a thought to generalise ($)
like Control.Category
generalises (.)
, and I\'ve done so with the code at the end of this post (also
There are two abstractions used for things like this in Haskell, one usings Arrow
s and the other Applicative
s. Both can be broken down into smaller parts than those used in base
.
If you go in the Arrow
direction and break down the capabilities of Arrows into component pieces, you'd have a separate class for those arrows that are able to lift arbitrary functions into the arrow.
class ArrowArr a where
arr :: (b -> c) -> a b c
This would be the opposite of ArrowArr
, arrows where any arbitrary arrow can be dropped to a function.
class ArrowFun a where
($) :: a b c -> (b -> c)
If you just split arr
off of Arrow
you are left with arrow like categories that can construct and deconstruct tuples.
class Category a => ArrowLike a where
fst :: a (b, d) b
snd :: a (d, b) b
(&&&) :: a b c -> a b c' -> a b (c,c')
If you go in the Applicative
direction this is a Copointed "Applicative
without pure
" (which goes by the name Apply).
class Copointed p where Source
copoint :: p a -> a
class Functor f => Apply f where
(<.>) :: f (a -> b) -> f a -> f b
When you go this way you typically drop the Category
for functions and instead have a type constructor C a
representing values (including function values) constructed according to a certain set of rules.