gpt4 book ai didi

haskell - IO中的简单计数器

转载 作者:行者123 更新时间:2023-12-02 05:44:36 25 4
gpt4 key购买 nike

我正在尝试使用 IO 创建一个无限增加 1 的简单计数器。

从那以后我就一直在挠头……

理想情况下,我想做一些类似的事情

tick = do putStr (counter)
counter + 1
where counter = 0

然后重复这个过程。然后重复前 2 个表达式。或类似的东西:
tick = tick'
where
counter = 1
tick' counter | counter > 0 = do putStrLn (show counter)
tick' (counter + 1)
| otherwise = tick

这给了我错误:/

任何帮助表示赞赏:)

最佳答案

有几种方法可以在不使用可变单元格的情况下做到这一点。您已经在第二次尝试中做到了,只是有一点错误。您需要将初始值传递给 tick'函数,而不是“设置它”(haskell 没有分配变量的想法——只有定义。如果出现 x = y 行,x 将在其整个生命周期内为 y)。

tick = tick' 0
where ...
counter = 0线路没有做任何事情;它正在定义一个从未使用过的名称。 counter用于 tick'函数被绑定(bind)为其参数之一(并隐藏定义为 0 的参数)。花点时间考虑一下,看看这是否有意义。

有一个很好的“高阶”方式我们也可以做到这一点。本质上,我们想要运行无限长的代码块:
do
print 0
print 1
print 2
...

有一个函数叫做 sequence :: [IO a] -> IO [a] (见下面的警告),它将采取行动列表并构造一个行动。所以如果我们可以构造列表 [print 0, print 1, print 2, ...]然后我们可以将它传递给 sequence构建我们正在寻找的无限长的 block 。

请注意,这是 Haskell 中一个非常重要的概念: [print 0, print 1, print 2]不打印这三个数字然后构造列表 [0,1,2] .相反,它本身是一个 Action 列表,其类型为 [IO ()] .列出 list 什么都不做;仅当您将操作绑定(bind)到 main 时它将被执行。例如,我们可能会说:
main = do
let xs = [putStrLn "hello", getLine >> putStrLn "world"]
xs !! 0
xs !! 0
xs !! 1
xs !! 1
xs !! 0

这将打印两次 hello , 两次得到一行并打印 world每个之后,然后打印一次 hello再次。

有了这个概念,很容易构建 Action 列表 [print 0, print 1, ...]列表理解:
main = sequence [ print x | x <- [0..] ]

我们可以稍微简化一下:
main = sequence (map (\x -> print x) [0..])
main = sequence (map print [0..])

所以 map print [0..]是操作列表 [print 0, print 1, ...]我们正在寻找,然后我们将其传递给 sequence将它们链接在一起。
sequence 这种模式很常见,有自己的 mapM :
mapM :: (a -> IO b) -> [a] -> IO [b]
mapM f xs = sequence (map f xs)

因此:
main = mapM print [0..]

尽可能简单。

关于性能的一点说明:由于我们没有使用这些函数的输出,我们应该使用 sequence_mapM_ , 带有尾随下划线,为此目的进行了优化。由于垃圾收集,通常这在 Haskell 程序中无关紧要,但在这个特定的用例中,由于各种微妙之处,这是一种特殊情况。你会发现没有 _ s,随着结果列表(在本例中为 [(),(),(),...])的构造但从未使用过,程序的内存使用量逐渐增加。

警告:我给出了 sequence 的类型签名和 mapM专门为 IO ,而不是一般的 monad,因此读者不必同时学习具有类型和类型类的操作的正交概念。

关于haskell - IO中的简单计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7829574/

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