Часто у вас есть что-то вроде Аппликатива
без чистого
или что-то вроде Монады
, но без возврат
. Пакет полугруппоид охватывает эти случаи с помощью Apply
и Bind
. Теперь у меня аналогичная ситуация с Arrow
, где я не могу определить значимую функцию arr
, но я думаю, что другие функции будут иметь смысл.
Я определил тип, содержащий функцию, и ее обратную функцию:
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
Теперь я не могу реализовать Arrow
, но что-то более слабое:
--"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')
Я думаю, что не могу реализовать эквивалент &&&
, поскольку он определен как f &&& g = arr (\ b -> (b, b)) >>> f *** g
, и (\ b -> (b, b))
необратимо. Тем не менее, как вы думаете, этот более слабый класс типов может быть полезен? Имеет ли это смысл даже с теоретической точки зрения?