【问题标题】:Is it possible?: Behavior t [Behavior t a] -> Behavior t [a]有可能吗?:行为 t [行为 t a] -> 行为 t [a]
【发布时间】:2014-01-19 12:17:54
【问题描述】:

有没有办法让Behavior t [a] 在时间 t 的 [a] 的值是在时间 t 包含在 Behavior t [Behavior t a] 中的值?即,具有以下类型的函数:

Behavior t [Behavior t a] -> Behavior t [a]

如果这不可能,是因为逻辑上的不可能性还是反应香蕉的限制?

【问题讨论】:

  • 类型签名是有效的,你能解释一下你的问题到底是什么吗?如果我猜对了,你想进行某种过滤吗?
  • 我不知道反应香蕉,但仍然有一个问题是这种类型是否有人居住。
  • 感谢您提到“类型是有人居住的”,它把我带到了 Haskell Wiki 上的 Curry-Howard 同构定理 wiki 页面。
  • 语义上Behavior aTime -> a,因此Behavior [Behavior a]Time -> [Time -> a]Behavior [a]Time -> [a]。你在寻找类似fix :: Behavior [Behavior a] -> Behavior [a]; fix as t = map ($ t) (as t) 的东西吗?
  • @Adrian Highly 建议与 Software FoundationsCertified Programming with Dependent Types 一起玩,如果你对这些东西感兴趣的话。

标签: haskell frp reactive-banana


【解决方案1】:

对于任何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 可遍历(单元素集合-IdentityTraversable 实例)并将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

因此,我们的函数恰好适用于那些也是单子的应用程序。

总结:当且仅当BehaviorMonad 时,您正在寻找的功能才会存在。因为它不是,所以很可能没有这样的功能。 (我相信如果有办法让它成为 monad,它会被包含在库中。)

【讨论】:

  • 我也几乎被这个想法所吸引,但后来我看到,根据我评论中展示的模型,对于任何 Functor 来说,它都应该是一个可能的、非平凡的函数。这显然仍然暗示着 Monad,所以我想我很好奇为什么模型是 monad 而实现却不是。
  • @J.Abrahamson 我猜原因是模型Time -> a 允许我们在任意时间访问任何值。但是在 FRP 实现中这是不可能的,我们通常可以访问“现在”或其他内容。我不确定,但这可能是原因。
  • @PetrPudlák:在Reader 类型中,可以使用Applicative 实例定义一元joinjoin ra = runReader <$> ra <*> ask。我认为我们可以从这个角度来看待这个问题:Behavior 缺少 runReader 的对应项。
  • @LuisCasillas 这是一个非常有趣的观点!我根本不认为应该有runBehavior :: Behavior a -> t -> a,但不应该有behaviorNow :: Behavior (Behavior a) -> Behavior a理论上实现为behaviorNow f t = f t t吗?
  • 稍微概括一下我之前的观点:另一种看待这个问题的方式是representable functors:任何Functor 同构到(->) r(对于某些r)是Monad。在 FRP 的情况下,Behavior(->) Time 在我们用来说明模型的元语言中存在同构,但在对象语言中我们无法实现这样的事情。跨度>
【解决方案2】:

正如 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 不是响应式香蕉中的单子。这是explained here

【讨论】:

    猜你喜欢
    • 2018-07-04
    • 2016-02-01
    • 1970-01-01
    • 2022-08-15
    • 2013-03-30
    • 1970-01-01
    • 2021-02-02
    • 2017-06-07
    • 1970-01-01
    相关资源
    最近更新 更多