【问题标题】:Why is this Applicative instance for StateT working?为什么 StateT 的这个 Applicative 实例有效?
【发布时间】:2020-10-19 13:26:45
【问题描述】:

我是 Haskell(和 CS)初学者。我正在通过haskellbook 工作。我正在为StateT 实现Applicative 实例,其中StateT 定义为:

newtype StateT s m a = StateT { runState :: s -> m (a, s) }

书中提到,要为StateT s m 创建一个Applicative 实例,我们需要对m 进行Monad 约束,而不是像人们所期望的那样使用Applicative 约束。对于书中引用的 SO 答案,我在阅读已接受的answer 时也得出了相同的结论。 但是,为了更好地理解,我尝试在m 上创建具有Applicative 约束的Applicative 实例,并成功编译。我还尝试了一些示例,它似乎工作正常。有人可以解释一下,这里有什么问题吗?

instance (Applicative m) => Applicative (StateT s m) where
  pure a = StateT $ \s -> pure $ (a, s)
  (<*>) :: (StateT s m (a -> b)) -> (StateT s m a) -> (StateT s m b)
  (StateT smf) <*> (StateT sma) = StateT $ \s -> (f) <$> (smf s) <*> (sma s)
                                  where
                                    f :: (a -> b, s) -> (a, s) -> (b, s)
                                    f (ff, s) = \(a, s) -> (ff a,s)

*StateT> s1 = StateT (\s -> return (4, s))
*StateT> s2 = map (+) s1
*StateT> s3 = StateT (\s -> return (20, s))
*StateT> runState (s2 <*> s3) * 10
(24,10)
*StateT>

编辑:正如@Koterpillar 建议我尝试使用状态也被修改的示例。我尝试使用this 示例。此外,hereMonad 约束版本,我认为它的行为也不尽如人意。我认为问题在于各州没有以某种方式联系在一起。如果有人能对这个话题有所了解,我将不胜感激。

【问题讨论】:

  • 请用修改状态的smfsma 试试这个。
  • 请删除 png 并替换为格式化文本。
  • @Michael Litchard 现在可以了吗?抱歉,我应该先发布文本。
  • 看起来不错。谢谢。 :)

标签: haskell functional-programming state monads applicative


【解决方案1】:

这是&lt;*&gt;StateT 应该做的:

  1. 以初始状态运行smf
  2. 运行sma,状态来自smf
  3. 返回这个最终状态

这就是您的代码的作用:

  1. 以初始状态运行smf
  2. 初始状态运行sma
  3. 返回这个最终状态

换句话说,错误在于smf引起的状态变化被丢弃

我们可以使用修改smf 中状态的代码来演示此问题。例如:

s1 = StateT $ \s -> return (const (), s + 1)
s2 = StateT $ \s -> return ((), s)

然后runState (s1 &lt;*&gt; s2) 0 将返回((), 1) 与标准实现,但((), 0) 与您的实现。

【讨论】:

  • 啊,我想我现在明白了。这也是我在Monad 约束版本中犯的错误。我必须将初始状态s 提供给smf,然后将状态从smf 返回到sma。我想过将这两种状态结合起来,但它们不是Semigroup
  • 这种状态线程让人想起bind。也许这就是我们需要 Monad 的原因。
  • 如果你改为&lt;&gt; 状态,那么你会得到一个Writer monad——实际上它有一个Monoid 约束。 (它需要Monoid,而不仅仅是Semigroup,为return 提供空状态。)
  • 哦,我还不知道Writer monads,但非常感谢。
猜你喜欢
  • 1970-01-01
  • 2013-09-11
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多