有一个更合适的概念是从一个profunctor那里制作免费的东西。然后我们可以类推。
由集合 X 生成的自由幺半群 Y 可以被认为是方程“Y=1+XY”的解。在 Haskell 表示法中
data List a = Nil | Cons a (List a)
由函子 F 生成的自由单子 M 可以被认为是方程“M=1+FM”的解,其中乘积“FM”是函子的组合。1 只是恒等函子。在 Haskell 表示法中那是
data Free f a = Pure a | Free (f (Free a))
从 profunctor P 中释放某些东西应该看起来像“A = 1 + PA”的解决方案 A。产品“PA”是profunctors的标准组成。1 是“身份”profunctor,(->)
。所以我们得到
data Free p a b = Pure (a -> b) | forall x.Free (p a x) (Free p x b)
这也是一个profunctor:
instance Profunctor b => Profunctor (Free b) where
lmap f (Pure g) = Pure (g . f)
lmap f (Free g h) = Free (lmap f g) h
rmap f (Pure g) = Pure (f . g)
rmap f (Free g h) = Free g (rmap f h)
如果profunctor很强大,那么免费版本也是如此:
instance Strong p => Strong (Free p) where
first' (Pure f) = Pure (first' f)
first' (Free f g) = Free (first' f) (first' g)
但实际上是Free p
什么?它实际上是一种叫做pre-arrow的东西。限制性的、自由的强函子是箭头:
instance Profunctor p => Category (Free p) where
id = Pure id
Pure f . Pure g = Pure (f . g)
Free g h . Pure f = Free (lmap f g) h
Pure f . Free g h = Free g (Pure f . h)
f . Free g h = Free g (f . h)
instance (Profunctor p, Strong p) => Arrow (Free p) where
arr = Pure
first = first'
直观地,您可以将 profunctor 的元素P a b
视为将a
-ish 事物转换为b
-ish 事物,规范示例由(->)
. Free P
是这些元素的未评估链,具有兼容(但不可观察)的中间类型。