gpt4 book ai didi

haskell - 2 个类似的 Haskell 函数使用 do 符号返回相同的结果,但一个被调用多次

转载 作者:行者123 更新时间:2023-12-03 20:23:04 28 4
gpt4 key购买 nike

nextState :: IO Int -> IO Int -- 0 1 0 2 0 1 0
nextState stateIO = do
value <- stateIO
putStrLn $ "Current state: " ++ show value
fmap (+1) stateIO

nextState' :: IO Int -> IO Int -- 0 1 2
nextState' stateIO = do
value <- stateIO
putStrLn $ "Current state: " ++ show value
return $ value + 1

main :: IO ()
main = do
let startStateIO = return 0 :: IO Int
let states = iterate nextState' startStateIO -- Use nextState or nextState'
stateInt <- states !! 3
print stateInt -- 3 in both cases

这段 Haskell 代码有 2 个函数,它们看起来具有相同的行为。但是,打印调用显示 nextState 被调用的次数比 nextState' 多得多。我有一个更大的项目,这是一个问题,我无法弄清楚如何转换该函数以使其被调用的次数最少,所以我无法修复它。

为什么会发生这种情况,我如何在一个不太简单的示例中防止这种情况发生?

注意,我实际项目中的fmap(+1)只是IO a -> IO a的一个函数,而不是fmap(a -> a ) - 整个事情在 IO 方面工作,而不是使用 (a->a)

修改内部值

最佳答案

这个例子应该更容易理解,类比:

twice :: IO () -> IO ()
twice act = do
() <- act
fmap id act -- like what you did in `nextState`

once :: IO () -> IO ()
once act = do
() <- act
return $ id () -- like what you did in `nextState'`

...或更短

twice :: IO () -> IO ()
twice act = act >> act

once :: IO () -> IO ()
once act = act

例如,

> twice (putStrLn "hello")
hello
hello
> once (putStrLn "hello")
hello

迭代 一次 不会做任何事情,因为它只是标识。

> iterate once (putStrLn "hello") !! 4
hello

迭代两次,然而...

Prelude> iterate twice (putStrLn "hello") !! 4
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello

关于haskell - 2 个类似的 Haskell 函数使用 do 符号返回相同的结果,但一个被调用多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67181745/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com