【问题标题】:Calling functions on a state monad "Stack" in Haskell在 Haskell 中调用状态单子“堆栈”上的函数
【发布时间】:2019-02-18 13:58:19
【问题描述】:

我们有以下任务给出的类型

newtype Trans state a = T {run :: state -> (a,state)}
type Stack a = Trans [Int] a

我想要的是写一个函数 1. push 将一个 Integer 入栈 2. pop 返回并移除最高对象

我试图通过状态 monads 谷歌来理解它们,我得到了这个概念,但我无法用给定的类型结构来实现它。

【问题讨论】:

  • 你确定这是Stack 的正确定义吗?我觉得应该是type Stack a = Trans [a] a
  • 而且我相信您被要求编写的函数是简单的“纯”函数state -> (a, state),然后您将了解 State monad 以及它如何简化此类堆栈的系列操作。为了编写这些基本函数,您无需了解 monad 如何“工作”。
  • @RobinZigmond 我不知道,也许吧,但我不认为这有什么不同,因为我们只有处理整数的任务
  • a 是对Stack 的操作的返回值,例如push :: Int -> Stack ()pop :: Stack Int
  • 谢谢,这是我想出来的: push :: Int -> Stack () pop :: Stack Int add :: Stack () (从堆栈中取两个元素,计算总和并放入它回到堆栈上)。我仍然不知道如何实现它。怎么写。

标签: haskell state monads


【解决方案1】:

Pop 和 Push 相当简单:

push :: Int -> Stack ()
push x = T { run = \st -> ((), x : st) }

pop :: Stack (Maybe Int)
pop = T
  { run = \st -> case st of
      (x : xs) -> (Just x, xs)
      _ -> (Nothing, st)
  }

popMaybe Int 的类型,因为堆栈可以为空。在这种情况下,我们只返回Nothing。 但是我们能用它做什么呢?好吧,没有Monad 实例就没什么了。让我们做一个。我们首先需要FunctorApplicative 实例:

instance Functor (Trans st) where
  fmap f (T r) = T
    { run = \st -> 
        let (result, state) = r st
        in (f result, state)
    }

instance Applicative (Trans st) where
  pure a = T { run = \st -> (a, st) }
  (<*>) (T fr) (T r) = T
    { run = \st ->
        let (result, state) = r st
            (f, nextState) = fr state
        in (f result, nextState)
    }

instance Monad (Trans a) where
  (>>=) (T r) f = T
    { run = \st ->
        let (result, state) = r st
        in run (f result) state
    }

它给了我们什么?我们终于可以使用我们的poppush 函数了:

simpleStack :: Stack Int
simpleStack = do
  push 10
  push 20
  push 30
  Just x <- pop
  return x

我们可以这样测试:

main :: IO ()
main = putStrLn $ show $ fst $ run simpleStack []

【讨论】:

  • 公平地说,您可以在没有Monad 实例的情况下使用pushpop;它只是更冗长:)
  • &lt;*&gt; 的定义是否正确?对我来说,st 应用于r 而不是fr 似乎很奇怪。通常状态是“从左到右”传递的,fr 是最左边的参数。
猜你喜欢
  • 2013-02-25
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
  • 2019-11-22
  • 2014-11-13
  • 1970-01-01
相关资源
最近更新 更多