使用>>的理由

时间:2013-11-30 17:14:30

标签: monads state-monad haskell

在真实世界的哈斯克尔chapter中,他们为(>>)提供了这样的理由:

  

当我们想要按特定顺序执行操作时,我们使用此功能,但不关心其结果是什么。

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

ghci > print "foo" >> print "bar"
"foo"
"bar"

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

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

但是为什么在这种情况下他们使用语句put gen' >>最终他们忽略了它的输出值。为什么上述功能不能像这样:

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

为了完成这个问题,我正在为上述背景添加相关的类型定义和函数:

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

get :: State s s
get = State $ \s -> (s, s)

put :: s -> State s ()
put s = State $ \_ -> ((), s)

type RandomState a = State StdGen a

1 个答案:

答案 0 :(得分:9)

因为put有副作用。它将某些东西粘贴到状态monad中,以后可以访问和修改。

它的返回值只是(),这很无聊,所以我们不关心它,但我们当然希望确保将新的随机生成器置于状态。

想到这样,状态monad实际上是一个函数s -> (a, s)。和put

put s = \oldState -> (() , s)

所以这有副作用,它正在抛弃旧状态并取而代之。考虑这个例子

  test = put 1 >> get >>= \x -> put 2 >> get >>= \y -> return (x, y)

  -- or with do notation
  test' = do
    put 1
    x <- get
    put 2
    y <- get
    return (x, y)

此处x1y2。显而易见,除了它的回报价值之外,还有其他有趣的效果。