【问题标题】:Implementing Applicative (<*>) for StateT为 StateT 实现 Applicative (<*>)
【发布时间】:2015-01-12 13:57:47
【问题描述】:

有人问过这个问题before,但没有真正的答案。事实上,公认的答案表明这是不可能的,尽管

  • StateT 是 Monad,因此是 Applicative 的超集。结果,标准库只使用(&lt;*&gt;) = ap
  • (正如 Petr 所指出的)组合应用程序总是产生一个应用程序。

我读过的关于使用的 MaybeT 实现之一

liftA2 (<*>) :: (Applicative f, Applicative f1) => f (f1 (a -> b)) -> f (f1 a) -> f (f1 b)

实现 Applicative 但我不能在这里工作。我正在进行的工作围绕以下方面尝试了很多选项:

-- (<*>) :: StateT s f (a -> b) -> State s f a -> State s f b
instance (Applicative f) => Applicative (StateT s f) where
    pure a =  StateT $ \s -> pure (a, s)
    (StateT f) <*> (StateT g) = StateT $ \s ->          -- f :: s -> m (a -> b, s),  g :: s -> m (a, s)
                                    let
                                        mabs = f s          -- mabs :: m (a -> b, s)
                                        mab = fmap fst mabs
                                        ms' = fmap snd mabs

                                    in undefined

我想知道我错过了什么,并希望我能在这个过程中学到一些关于 Applicative 的知识。

【问题讨论】:

  • 堆叠转换器与组合函子并不完全相同。因此,“组合应用程序总是产生一个应用程序”并没有真正的帮助。
  • ...如果您对(Monad f) =&gt; 没问题,那么任务当然很简单:只需将&gt;&gt;= 的定义内联到ap 的定义中,然后简化即可。跨度>

标签: haskell monad-transformers applicative


【解决方案1】:

Tony 使用了一些替代符号,Simon 的回答非常简洁,所以我最终得到了以下结果:

-- (<*>) :: StateT s f (a -> b) -> State s f a -> State s f b
instance (Monad f, Applicative f) => Applicative (StateT s f) where
    pure a =  StateT $ \s -> pure (a, s)
    StateT f <*> StateT a =
        StateT $ \s -> 
                f s >>= \(g, t) ->                   -- (f s) :: m (a->b, s)
                    let mapper = \(z, u) -> (g z, u) -- :: (a, s) -> (b, s)
                    in fmap mapper (a t)             -- (a t) :: m (a, s)

我必须声明 f 也是一个 Monad,但这没关系,因为它是 Monad 转换器定义的一部分,据我所知。

【讨论】:

    【解决方案2】:

    一个实现(取自Tony Morris' functional programming course)可能是

    (<*>) :: (Functor f, Monad f) =>
      StateT s f (a -> b)
      -> StateT s f a
      -> StateT s f b
    StateT f <*> StateT a =
      StateT (\s -> (\(g, t) -> (\(z, u) -> (g z, u)) <$> a t) =<< f s)
    

    【讨论】:

    • 使用一元绑定。
    • 没关系,因为 f 根据 Transformer 的定义是 Monad。我只需要将其余的去缩小化......
    • @leftaroundabout 已修复。
    猜你喜欢
    • 2013-09-11
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多