Often you have something like an Applicative
without pure
, or something like a Monad
, but without return
. The semigroupoid package covers these cases with Apply
and Bind
. Now I'm in a similar situation concerning Arrow
, where I can't define a meaningful arr
function, but I think the other functions would make perfect sense.
I defined a type that holds a function and it's reverse function:
import Control.Category
data Rev a b = Rev (a -> b) (b -> a)
reverse (Rev f g) = Rev g f
apply (Rev f _) x = f x
applyReverse (Rev _ g) y = g y
compose (Rev f f') (Rev g g') = Rev ((Prelude..) f g) ((Prelude..) g' f')
instance Category Rev where
id = Rev Prelude.id Prelude.id
(.) x y = compose x y
Now I can't implement Arrow
, but something weaker:
--"Ow" is an "Arrow" without "arr"
class Category a => Ow a where
first :: a b c -> a (b,d) (c,d)
first f = stars f Control.Category.id
second :: a b c -> a (d,b) (d,c)
second f = stars Control.Category.id f
--same as (***)
stars :: a b c -> a b' c' -> a (b,b') (c,c')
...
import Control.Arrow
instance Ow Rev where
stars (Rev f f') (Rev g g') = Rev (f *** g) (f' *** g')
I think I can't implement the equivalent of &&&
, as it is defined as f &&& g = arr (\b -> (b,b)) >>> f *** g
, and (\b -> (b,b))
isn't reversable. Still, do you think this weaker type class could be useful? Does it even make sense from a theoretical point of view?
Arrow
functions exactly the definition of a category ? – EmotionCategory
functions are the definition of a category. Well, morphisms, anyway (and no laws)—as I understand it,Category
corresponds to a subcategory of Hask which has the same objects (all types) but different morphisms.Arrow
adds a lot more structure, but I don't know enough to say anything about what sort of structure. – NadabbCategory
specifies a category whose objects are those of Hask with arrows given by some 2-ary type constructor.Functor
describes a subcategory of Hask whose arrows are those of Hask with objects given by some 1-ary type constructor.Applicative
maps the monoidal structure of(,)
to theFunctor
, while(&&&)
etc. map it to theCategory
. Andarr
gives a functor from Hask to theCategory
. – UkuleleArrowApply
makes theCategory
cartesian closed, giving the full power of lambda calculus with higher-order arrows, currying, etc., and the ability to map all of that from Hask to theCategory
. Arrows from a fixed object then give the usualReader
monad structure, which is whyKleisli m a b
is isomorphic toReaderT a m b
. – UkuleleArrow
instances indeed fail to have products. – Ukulele