标签: state-monad

状态单子如何工作?(无代码说明)

在过去的几个月里,我一直在花一些空闲时间来阅读有关 Monad 的文章。自从大学时代以来,我就没有使用过函数式语言。所以我不太记得 Haskell,当然也不知道 Scalaz。

学习洋葱、墨西哥卷饼和三明治,同时尝试将这些食物与大量 Haskell 代码关联起来,这是一段艰难的时光。幸运的是,我偶然发现了两篇关键文章,这让我大吃一惊:图片中的单子,以及另一个来自命令式编码背景的人,他简单地写了相当于以下内容的内容:

a -> b becomes m[a] -> m[b] (functor)
a -> m[b] becomes m[a] -> m[b] (monad)
and applicative is just a "function with context"
Run Code Online (Sandbox Code Playgroud)

连同描述bind目的的最简单的句子一起,内函子的许多类别爆炸并变得简单。

Identity、List、Maybe 等突然变得有意义了。在这些知识的推动下,我开始尝试使用一元类型在 C++ 中尝试一些 TMP,看看它会如何实现。

很快我就想传播状态。我想我现在读到的关于状态 monad 和 monad 转换器的文章比我一开始读的关于 monad 的文章还要多,但我一生都无法理解它们。我确信许多键盘已经磨损了,因为这些主题上输入的所有单词都回答了像我这样的人。

但我请你再受一点苦。

a -> s -> (b, s)
Run Code Online (Sandbox Code Playgroud)

函数接受一个值和某个状态,返回一个新值和(可能)修改后的状态。Bind 显然需要将返回值和状态传播到下一个函数中。

我的问题是这样的: monad 的工作是因为它们强加了一个结构。坚持结构并遵守法律会带来乐趣和彩虹。然而 a -> s -> (b, s) 看起来并不像一元 a -> m[b]。

即使应用'a',它仍然是s -> (b, s)。区别在于后一个函数采用(单子?)STATE 并返回带有值的状态。而常规形式是:接受一个 VALUE 并返回一个 WRAPPED 值。

传入的参数以及返回类型的形式都会有所不同。然而许多文章都说这显然看起来像一个单子。对我来说肯定不是。

如果我要放松一下我被告知必须持有的观点:它不是将 m[a] 绑定到 …

monads state-monad

5
推荐指数
1
解决办法
829
查看次数

何时以及为何使用 State Monad?

我可以编写一个 State Monad(在 Scala/Java 中),并且当我看到其他人使用它时,我几乎可以遵循逻辑。我不完全理解它正在解决的问题。它是一个包裹 funciton 的 monad S => (S,A)

因此,当您通过 flatMap 嵌套导致 State Monad 的函数时,它会为您提供一组对数据执行的指令/操作(S)(但尚未执行它们)。直到最后,当你给它一个S并告诉它运行时,它才起作用。

与仅编写函数来完成相同的事情相比,这样做有什么好处?

Monad 不会组合,因此以这种方式拥有这些功能似乎对设计有很大的影响。如果您提供示例代码,请使用 Java 或 Scala(因为我不明白如何阅读 Haskell 或其他严格的函数式语言)。汉克斯!

scala state-monad

5
推荐指数
1
解决办法
457
查看次数

如何在 IO 异常处理程序中保留 monad 堆栈的状态?

考虑以下程序。

import Control.Monad.State
import Control.Monad.Catch

ex1 :: StateT Int IO ()
ex1 = do
    modify (+10)
    liftIO . ioError $ userError "something went wrong"

ex2 :: StateT Int IO ()
ex2 = do
    x <- get
    liftIO $ print x

ex3 :: StateT Int IO ()
ex3 = ex1 `onException` ex2

main :: IO ()
main = evalStateT ex3 0
Run Code Online (Sandbox Code Playgroud)

当我们运行程序时,我们得到以下输出。

$ runhaskell Test.hs
0
Test.hs: user error (something went wrong)
Run Code Online (Sandbox Code Playgroud)

但是,我预计输出如下。

$ runhaskell Test.hs
10
Test.hs: user error (something …
Run Code Online (Sandbox Code Playgroud)

haskell exception state-monad io-monad

5
推荐指数
1
解决办法
76
查看次数

自定义类型的 `bind` 的 Haskell 实例

我正在尝试为(>>=)自定义类型的绑定运算符创建一个实例ST a

我找到了这种方法,但我不喜欢那个硬编码的0

有没有办法在没有硬编码0和尊重函数类型的情况下实现它?

newtype ST a = S (Int -> (a, Int))
    
-- This may be useful to implement ">>=" (bind), but it is not mandatory to use it
runState :: ST a -> Int -> (a, Int)
runState (S s) = s
        
instance Monad ST where
      return :: a -> ST a
      return x = S (\n -> (x, n))
       
      (>>=) :: ST a -> (a -> ST b) -> ST …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad

5
推荐指数
0
解决办法
95
查看次数

在复合 StateT/Maybe monad 中,如何取任何一种成功的可能性?

在 Haskell 中,这是一个结合了 State 和 Maybe monad 的 monad:

type StatefulMaybe a = StateT Int Maybe a
Run Code Online (Sandbox Code Playgroud)

这是一个可以成功(返回一个值)或失败的计算。如果成功,它会携带一个状态以及返回值。

我想写一个函数

choice :: StatefulMaybe a -> StatefulMaybe a -> StatefulMaybe a
Run Code Online (Sandbox Code Playgroud)

这需要两次这样的计算并返回第一个成功的(如果有的话)。只有成功计算的状态变化才会被推进。

事实上,经过一些实验,我想出了如何写这个。这里是:

orMaybe :: Maybe a -> Maybe a -> Maybe a
orMaybe (Just x) _ = Just x
orMaybe Nothing x = x

choice :: StatefulMaybe a -> StatefulMaybe a -> StatefulMaybe a
choice mx my = StateT (\s ->
    (runStateT mx s) `orMaybe` (runStateT my s)
  )
Run Code Online (Sandbox Code Playgroud)

有用:

foo …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad monad-transformers

5
推荐指数
1
解决办法
79
查看次数

haskell - 状态monad函数得到?

根据State Monad的get函数提出的一个问题:

如果我跑

runState get 1

我得到了结果

(1,1)

这对我来说没问题,因为get函数将结果值设置为状态,在这种情况下状态为1.因此,(1,1)是结果.好.

但是,如果我跑

runState(do {(a,b)< - get; return a})(False,0)

我得到了结果

(假,(假,0))

这个我不明白.

get函数将结果值设置为状态并保持状态不变.所以我期待的是这样的事情

((假,0),(假,0))

与此相同

runState(do {(a,b)< - get; return b})(False,0)

结果是

(0,(假,0))

如上所述,我不再理解这一点.

所以,如果你能解释我这个奇怪的结果,那将是非常好的.;)

提前致谢

最好的祝福,

吉米

monads haskell state-monad

4
推荐指数
2
解决办法
1852
查看次数

使用的理由>>

在真实世界的Haskell 章节中,他们给出了(>>)这样的理由:

当我们想要按特定顺序执行操作时,我们使用此函数,但不关心它的结果是什么.

然后他们给出了一个很好的例子来证明它:

ghci > print "foo" >> print "bar"
"foo"
"bar"
Run Code Online (Sandbox Code Playgroud)

在本章的后面,他们使用相同的概念在State monad中生成随机值:

getRandom :: Random a => RandomState a
getRandom =
  get >>= \gen ->
  let (val, gen') = random gen in
  put gen' >>
  return val
Run Code Online (Sandbox Code Playgroud)

但是为什么在这种情况下他们put gen' >>最终会忽略它的输出值而使用该陈述.为什么以上功能不能像这样:

getRandom :: Random a => RandomState a
getRandom =
  get >>= \gen ->
  let (val, gen') = random gen in
  return val
Run Code Online (Sandbox Code Playgroud)

只是为了完成这个问题,我正在为上面的上下文添加相关的类型定义和函数:

newtype State s a = State {
  runState :: …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad

4
推荐指数
1
解决办法
172
查看次数

还有一次......我可以举一个做我想要的状态monad的例子吗?

我试图了解读者和/或州monad的实际需求.我见过的所有例子(包括很多关于stackoverflow,因为我已经寻找合适的例子,我可以使用以及各种书籍和博客文章)的形式(伪代码)

 f = do
        foo <- ask
        do something with foo

 g = do
        foo <- ask
        do something else using foo

 h = runReader
       (
           f
           g
       )
Run Code Online (Sandbox Code Playgroud)

换句话说,调用两个函数并(可能)从一个调用到下一个调用保持某种状态.但是,我没有发现这个例子特别令人信服,因为(我认为)我可以让f返回一些状态,然后将该状态传递给g.

我希望看到一个例子,使用一个整数(比如说)作为要保留的状态,而不是两个顺序调用f然后从中心位置调用g,而不是调用f然后在内部调用g然后在主程序中更改了状态(如果状态monad).

我见过的大多数(实际上是所有)示例花费了大量时间专注于monad的定义,然后展示如何设置单个函数调用.对我来说,这就是能够进行嵌套调用并让状态随身携带,以证明它为什么有用.

haskell state-monad reader-monad

4
推荐指数
2
解决办法
1758
查看次数

构造状态Monad中的错误处理的最小Haskell示例

我正在扭曲我的大脑,试图理解如何将Statemonad与... 结合起来Maybe.

让我们从一个具体(并且故意琐碎/不必要)的例子开始,我们使用Statemonad来查找数字列表的总和:

import Control.Monad.State

list :: [Int]
list = [1,4,5,6,7,0,3,2,1]

adder :: Int
adder = evalState addState list

addState :: State [Int] Int
addState = do
  ms <- get
  case ms of
    []     -> return 0
    (x:xs) -> put xs >> fmap (+x) addState
Run Code Online (Sandbox Code Playgroud)

凉.

现在让我们修改它,以便Nothing在列表包含数字时返回a 0.换句话说,evalState addState' list应该返回Nothing(因为list包含a 0).我觉得它可能看起来像这样......

addState' :: State [Int] (Maybe Int)
addState' = do
  ms <- get
  case …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad monad-transformers maybe

4
推荐指数
1
解决办法
171
查看次数

这个State monad代码是如何工作的?

此代码来自本文

我已经能够遵循它直到这一部分.

module Test where

type State = Int

data ST a = S (State -> (a, State))

apply        :: ST a -> State -> (a,State)
apply (S f) x = f x

fresh =  S (\n -> (n, n+1))

instance Monad ST where
    -- return :: a -> ST a
    return x   = S (\s -> (x,s))

    -- (>>=)  :: ST a -> (a -> ST b) -> ST b
    st >>= f   = S (\s -> let …
Run Code Online (Sandbox Code Playgroud)

monads haskell state-monad

4
推荐指数
2
解决办法
278
查看次数