【发布时间】:2014-10-09 02:35:11
【问题描述】:
我在Helm 中四处乱窜,试图创建一个有状态的信号类型,该类型将携带有关自上次采样以来值是否已更改的附加信息。我已经设法使新信号类型成为Functor 的实例,但我正在努力定义Applicative 的<*> 函数,这将允许我将多个信号提升到一个函数中。
到目前为止,我定义的唯一信号是constant 信号,它在初始采样时将具有Changed x,之后将具有Unchanged x。其他信号会更复杂,并使用Elerea.stateful 来确定值是否已更改。
lift2 在下面的代码中不起作用,因为尚未定义 <*>。
import qualified FRP.Elerea.Simple as Elerea
import Control.Applicative
data Event a = Changed a | Unchanged a
instance Functor Event where
fmap f (Changed a) = Changed (f a)
fmap f (Unchanged a) = Unchanged (f a)
instance Applicative Event where
pure = Unchanged
(Changed f) <*> (Changed x) = Changed (f x)
(Changed f) <*> (Unchanged x) = Changed (f x)
(Unchanged f) <*> (Changed x) = Changed (f x)
(Unchanged f) <*> (Unchanged x) = Unchanged (f x)
data Signal a = Signal (Elerea.SignalGen (Elerea.Signal (Event a)))
instance Functor Signal where
fmap f (Signal x) = Signal ((fmap . fmap . fmap) f x)
instance Applicative Signal where
pure = Signal . pure . pure . pure
--(<*>) = ??
{-| Creates a signal that never changes. -}
constant :: a -> Signal a
constant x = Signal $ Elerea.stateful (Changed x) (\_ -> Unchanged x)
lift :: (a -> b) -> Signal a -> Signal b
lift = fmap
lift2 :: (a -> b -> c) -> Signal a -> Signal b -> Signal c
lift2 f a b = fmap f a <*> b
我目前正在使用的完整代码位于 Github。
【问题讨论】:
-
为什么
Signal包含SignalGen? -
所以 Elerea 定义了
Elerea.Signal和Elerea.SignalGen。 Elerea 中的信号是无事件的,只是恒定的值流。我正在尝试定义一个新的信号类型,更接近信号的Elm 想法,可用于确定主元素是否需要重新计算和重新渲染(当值自上次采样以来发生变化时)。 -
另见Helm issue(赏金由我创建)。
-
也许更清楚:
Elerea.stateful返回一个Elerea.SignalGen (Elerea.Signal a),我正在尝试包装它。