州monad和learnyouahaskell.com

时间:2012-03-14 08:08:05

标签: haskell monads

我正在阅读Learn You a Haskell's guide on the state monad,但我无法理解它,因为堆栈示例无法编译。在指南中,他使用了以下代码:

import Control.Monad.State  

type Stack = [Int]

pop :: State Stack Int  
pop = State $ \(x:xs) -> (x,xs)  

push :: Int -> State Stack ()  
push a = State $ \xs -> ((),a:xs) 

虽然我理解它应该做什么,但它不会编译。我不知道为什么。错误消息是:

Stack.hs:6:7: Not in scope: data constructor `State'

Stack.hs:9:10: Not in scope: data constructor `State'

这对我没有意义,因为据我所知,“State”实际上是一个数据构造函数,定义为

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

指南是“错误的”,如果是,我该如何解决?

1 个答案:

答案 0 :(得分:0)

已接受的答案已经提到使用state中的Control.Monad.State函数而不是State类型。但是,如果您只是在ghci中加载了相关的mtl软件包,尝试使用已接受的答案,则它仍然会失败:

Prelude Control.Monad.State> push a = state $ \xs -> ((), a:xs)

<interactive>:5:1: error:
    • Non type-variable argument in the constraint: MonadState [a] m
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        push :: forall a (m :: * -> *). MonadState [a] m => a -> m ()

要解决此问题,这里有两个选项:

  1. 要么指定函数的类型签名(无论如何都应指定)。
  2. 按照错误中的说明添加FlexibleContexts编译器扩展。

我们可以指定类型签名:

module LearnYouAHaskell where

import Control.Monad.State as State

push :: Int -> State.State [Int] ()
push a = State.state $ \xs -> ((), a:xs)

上面的代码可以正常编译和运行。

或者我们可以添加语言扩展名,以便它可以推断函数类型。

{-# LANGUAGE FlexibleContexts #-}
module LearnYouAHaskell where

import Control.Monad.State as State

push a = State.state $ \xs -> ((), a:xs)

哪个也可以正常工作。