我有这个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
取决于subtree
和according to a paper on applicative do-notation,在这种情况下,我们不能贬低到Applicative。似乎没有办法解决这个问题;我们需要一个monad从嵌套的深处漂浮起来。
这是真的吗?我可以有把握地得出结论,只有扁平结构可以单独使用应用效果折叠吗?
答案 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
concat
为Applicative
的原因。 f
只允许你将迄今为止无关的Free
粉碎在一起。
免费monad的f
构造函数包含一整个Free f
个Ap
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
我们有f
和traverse
。我的第一直觉是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}}。