一个可遍历的F-代数,是否有可能在一个应用代数上具有一个变形?

时间:2018-01-28 17:38:46

标签: haskell category-theory catamorphism

我有这个F-Algebra(introduced in a previous question),我想在它上面投射一个有效的代数。通过绝望的审判,我设法将一个有效的monadic catamorphism放在一起。我想知道它是否可以推广到一个应用程序,如果没有,为什么。

这是我定义Traversable

的方式
instance Traversable Expr where
    traverse f (Branch xs) = fmap Branch $ traverse f xs
    traverse f (Leaf   i ) = pure $ Leaf i

这是monadic catamorphism:

type AlgebraM a f b = a b -> f b

cataM :: (Monad f, Traversable a) => AlgebraM a f b -> Fix a -> f b
cataM f x = f =<< (traverse (cataM f) . unFix $ x)

这就是它的工作原理:

λ let printAndReturn x = print x >> pure x
λ cataM (printAndReturn . evalSum) $ branch [branch [leaf 1, leaf 2], leaf 3]
1
2
3
3
6
6

我现在的想法是我可以这样重写:

cataA :: (Applicative f, Traversable a) => AlgebraM a f b -> Fix a -> f b
cataA f x = do
    subtree <- traverse (cataA f) . unFix $ x
    value <- f subtree
    return value

不幸的是,此处的value取决于subtreeaccording to a paper on applicative do-notation,在这种情况下,我们不能贬低到Applicative。似乎没有办法解决这个问题;我们需要一个monad从嵌套的深处漂浮起来。

这是真的吗?我可以有把握地得出结论,只有扁平结构可以单独使用应用效果折叠吗?

1 个答案:

答案 0 :(得分:5)

  

我能否可以得出结论,只有扁平结构可以单独使用应用效果折叠?

你可以再说一遍!毕竟,“展平嵌套结构”正是使monad成为monad的原因,而不是只能组合相邻结构的Applicative。比较两个抽象的签名(的版本):

class Functor f => Applicative f where
    pure :: a -> f a
    (<.>) :: f a -> f b -> f (a, b)

class Applicative m => Monad m where
    join :: m (m a) -> m a

Monad添加到Applicative的内容是将嵌套 m压缩为一个m的能力。这就是[] join concatApplicative的原因。 f只允许你将迄今为止无关的Free粉碎在一起。

免费monad的f构造函数包含一整个Free fAp s,而免费应用程序的Ap f构造函数只包含一个data Free f a = Return a | Free (f (Free f a)) data Ap f a where Pure :: a -> Ap f a Cons :: f a -> Ap f b -> Ap f (a, b) ,这并非巧合。 }。

Applicative

希望这能为您提供一些直觉,告诉您为何不能使用cataA :: (Traversable f, Applicative m) => (f a -> m a) -> Fix f -> m a cataA f (Fix xs) = _ 折叠树。

让我们玩一些型网球,看看它是如何震撼的。我们想写

xs :: f (Fix f)

Traversable我们有ftraverse。我的第一直觉是f cataA f (Fix xs) = _ $ traverse (cataA f) xs 折叠包含的子树:

m (f a) -> m a

洞现在的目标类型为f :: f a -> m a。由于有m敲门,让我们尝试在f下转换包含的cataA f (Fix xs) = _ $ fmap f $ traverse (cataA f) xs

m (m a) -> m a

现在我们的目标类型为join,即Monad。所以你确实需要一个{{1}}。