繁体   English   中英

尽管复制粘贴了准确的代码并导入了模块,但数据构造函数不在 scope 中

[英]Data constructor not in scope despite copy-pasting exact code and importing module

我正在尝试运行 Haskell 在线书籍中最简单的示例之一,您可以在其中实现有状态的 function 对一堆数字进行建模。 我正在使用的示例中的代码是 ( http://learnyouahaskell.com/for-a-few-monads-more#state ):

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)  

然而,当尝试在 Prelude 中加载它时,我得到:

state.hs:6:7: error:
    Data constructor not in scope:
      State :: ([a0] -> (a0, [a0])) -> State Stack Int
  |
6 | pop = State $ \(x:xs) -> (x,xs)  
  |       ^^^^^

state.hs:9:10: error:
    Data constructor not in scope:
      State :: ([Int] -> ((), [Int])) -> State Stack ()
  |
9 | push a = State $ \xs -> ((),a:xs)  
  |          ^^^^^
Failed, no modules loaded.

我错过了什么??? 这个例子有什么问题吗?

我只是希望简单地加载模块而不会出现错误。 不知道出了什么问题。

有点令人惊讶的是, Control.Monad.State模块不包含名为State的数据构造函数。 如果它简单地定义就是这种情况

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

– 它曾经mtl库的版本 1 中执行过,但现在不再执行了。 从 2.0 版本开始,该模块只导出一个名为State类型同义词,它实际上是从Control.Monad.Trans.State重新导出的,因此实现:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
type State s = StateT s Identity

Identity monad 使这个行为使得m (a,s)本身与简单(a,s)同构,所以最终StateT s Identity a确实与State' sa同构。 然而,它更通用: StateT是一个monad 转换器,也可以堆叠在其他 monadic 操作之上,例如IO

所以你不能使用State值构造函数,但你可以使用state ,它的行为与Statemtl-1.1中的行为完全相同。 (除非你不能对其进行模式匹配,但你仍然可以使用runState 。)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM