有没有办法让Behavior t [a]
[a] 在时间 t 的值是Behavior t [Behavior t a]
在时间 t 包含在 a 中的值?即,具有以下类型的函数:
Behavior t [Behavior t a] -> Behavior t [a]
如果这是不可能的,那是因为逻辑上的不可能性还是反应香蕉的限制?
有没有办法让Behavior t [a]
[a] 在时间 t 的值是Behavior t [Behavior t a]
在时间 t 包含在 a 中的值?即,具有以下类型的函数:
Behavior t [Behavior t a] -> Behavior t [a]
如果这是不可能的,那是因为逻辑上的不可能性还是反应香蕉的限制?
对于 any 来说,该类型是微不足道的Applicative
:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Control.Monad
import Data.Functor.Identity
import qualified Data.Traversable as T
f' :: (Applicative f) => f [f a] -> f [a]
f' = const $ pure []
这显然不是你想要的。所以让我们要求居住
(Traversable t) => Behavior u (t (Behavior u a)) -> Behavior u (t a)
或者更一般地说,我们可以构建哪些应用程序
(T.Traversable t) => f (t (f a)) -> f (t a)
这适用于任何f
也是单子的人:
f :: (Monad m, T.Traversable t) => m (t (m a)) -> m (t a)
f = join . liftM T.sequence
一个明显的问题出现了:如果一个应用程序有这样的f
,它必须是一个 monad 吗?答案是肯定的。我们只适用f
于可Identity
遍历(单元素集合 - 的Traversable
实例Identity
)并构造join
为
g :: (Applicative m) => (forall t . (T.Traversable t) => m (t (m a)) -> m (t a))
-> (m (m a) -> m a)
g f = fmap runIdentity . f . fmap Identity
因此,我们的函数恰好适用于那些也是单子的应用程序。
总结:当且仅当Behavior
是 a时,您正在寻找的功能才会存在Monad
。因为它不是,很可能没有这样的功能。(我相信如果有办法让它成为一个单子,它会被包含在图书馆里。)
正如 Petr 已经指出的那样,这样的功能
flatten :: Behavior t [Behavior t a] -> Behavior t [a]
当且仅当类型Behavior t
是 monad 时才存在。
这里有一个直接的方式来看待这个:
join :: Behavior t (Behavior t a) -> Behavior t a
join = map head . flatten . map (:[])
flatten = join . map sequence
但是,由于各种原因,Behavior t
它不是反应香蕉中的单子。这是解释here。