如何解决使用状态 monad 时的意外行为 - 状态包裹在列表中
我现在正在学习 Haskell,我正在尝试与状态 Monad 合作。
我递归地要求用户输入并将其附加到列表中。当我在同一个函数中实现 IO 处理和状态执行时,程序按预期工作:
picture_count
由于我不明白的原因,当我将状态处理函数与 IO 函数分开时,返回的状态是用一个列表包装的:
import Control.Monad.State
push :: String -> State [String] ()
push a = state $ \xs -> ((),a:xs)
testingState :: State [String] ()
testingState = do
push ("testing state!")
return ()
handleState :: [String] -> IO()
handleState prevIoUsstack = do
line <- getLine
let userIntput = words line
let stack = userIntput ++ prevIoUsstack
let newStack = (execState testingState) stack
handleState newStack
main :: IO
main = do
handleState []
handleState :: [String] -> IO()
handleState prevIoUsstack = do
line <- getLine
let newStack = changeState line stack
handleState newStack
changeState :: String -> [String] -> [String]
changeState line prevIoUsstack = do
let userIntput = words line
let stack = userIntput ++ prevIoUsstack
let newStack = (execState testingState) stack
return newStack
main = do
handleState []
另外,我只能在 • Couldn't match type ‘[Char]’ with ‘Char’
Expected type: [String]
Actual type: [[String]]
函数外部展平数组,在函数内部这样做是行不通的。
解决方法
您在 do
中使用了 return
和 changeState
。由于 do
块的类型是 [String]
,它将使用 Monad
类型类的列表实例,这意味着 return :: Monad m => a -> m a
将包装一个元素在列表中。
您可以将 changeState
函数实现为:
changeState :: String -> [String] -> [String]
changeState line previousStack = execState testingState (words line ++ previousStack)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。