Haskell 中惰性和 I/O 如何协同工作?

2024-02-18

我试图更深入地了解 Haskell 中的惰性。

我今天想象了以下片段:

data Image = Image { name :: String, pixels :: String }

image :: String -> IO Image
image path = Image path <$> readFile path

这里的吸引力在于我可以简单地创建一个 Image 实例并将其传递;如果我需要图像数据,它将被延迟读取 - 如果不需要,则可以避免读取文件的时间和内存成本:

 main = do
   image <- image "file"
   putStrLn $ length $ pixels image

但实际上是这样的吗?惰性如何与 IO 兼容?无论我是否访问都会调用readFilepixels image或者如果我从不引用它,运行时会不会对该 thunk 进行评估?

如果图像确实是延迟读取的,那么 I/O 操作是否可能会无序发生?例如,如果在调用后立即怎么办?image我删除文件?现在 putStrLn 调用在尝试读取时将找不到任何内容。


惰性如何与 I/O 兼容?

简短回答:事实并非如此。


长答案:IO操作是严格按顺序进行的,其原因几乎与您所想到的一样。当然,任何对结果进行的纯计算都可能是惰性的;例如,如果您读入文件,进行一些处理,然后打印出一些结果,则可能不会评估输出不需要的任何处理。但是,整个文件都会被读取,甚至是您从未使用过的部分。如果您想要惰性 I/O,大约有两种选择:

  • 滚动您自己的显式延迟加载例程等,就像使用任何严格的语言一样。看起来很烦人,这是理所当然的,但另一方面,Haskell 是一种很好的、​​严格的、命令式的语言。如果您想尝试一些新的有趣的东西,请尝试查看迭代者 http://okmij.org/ftp/Streams.html.

  • 像一个作弊的骗子一样作弊。功能such as hGetContents http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/System-IO.html#v%3AhGetContents将为您执行惰性的、按需的 I/O,不问任何问题。有什么问题吗?它(从技术上讲)破坏了引用透明度。纯代码可能会间接导致副作用,如果您的代码确实很复杂,则可能会发生涉及副作用排序的有趣事情。hGetContents和朋友们都实施了using unsafeInterleaveIO http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base/System-IO-Unsafe.html#v%3AunsafeInterleaveIO,这就是……正如罐头上所说的那样。它远不如使用unsafePerformIO,但请考虑自己受到警告。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 中惰性和 I/O 如何协同工作? 的相关文章

  • 为什么 ZipList 不是 List 的默认应用实例

    我目前正在学习 Haskell 中的应用程序 如果我没记错的话 列表有两个不同的应用实例 List and ZipList 第二个被定义为包装列表值的新类型 这ZipList应用实例对我来说似乎更直观 这可能是一个愚蠢的问题 但有具体原因吗
  • 我该如何实现这个折叠功能呢?

    给出了两种数据类型 颜色 和 植物 data Color Red Pink White Blue Purple Green Yellow deriving Show Eq data Plant Leaf Blossom Color Stal
  • 带有 RankNTypes 扩展的奇怪类型推断

    我正在尝试在 Haskell 中尝试 System F 类型 并通过以下方式实现了自然数的 Church 编码type 当加载这段代码时 OPTIONS GHC Wall LANGUAGE RankNTypes type CNat fora
  • 检查对以下内容的理解:“变量”与“变量” “价值”、“功能”与“抽象”

    这个问题是后续问题this one https stackoverflow com questions 25327705 is function a sort of variable 25329157 25329157在学习 Haskell
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre
  • 如何打乱列表?

    如何从一组数字 1 2 3 直到我击中x 我的计划是重新调整列表 1 2 3 并把它砍在x chopAt 3 2 3 1 2 3 chopAt 3 2 1 3 2 1 3 chopAt 3 3 1 2 3 chopAt chopAt x y
  • 类型级别集结合律的证明

    我试图证明类型级函数Union https hackage haskell org package type level sets 0 8 5 0 docs Data Type Set html t Union是关联的 但我不确定应该如何完
  • C++ 概念与 Haskell 类型类有何不同?

    Concepts TS 中的 C 概念最近已合并到 GCC 主干中 概念允许人们通过要求类型满足概念的条件 例如 可比较 来约束通用代码 Haskell 有类型类 我对 Haskell 不太熟悉 概念和类型类如何相关 概念 由概念 TS 定
  • 迭代打印列表中的每个整数

    假设我有一个整数列表l 1 2 我想打印到stdout Doing print l产生 1 2 假设我想打印不带大括号的列表 map print l产生 No instance for Show IO arising from a use
  • 改进迭代文本解析的 clojure lazy-seq 使用

    我正在编写一个 Clojure 实现这次编码挑战 http biostar stackexchange com questions 1759 code golf mean length of fasta sequences 尝试找出 Fas
  • Parsec.Expr 具有不同优先级的重复前缀

    Parsec Expr buildExpressionParser 的文档说 相同优先级的前缀和后缀运算符只能出现一次 即 如果 为前缀否定 则不允许使用 2 但是 我想解析这样的字符串 具体来说 考虑以下语法 sentence ident
  • cabal install wx 缺少 C 库

    Env 操作系统 feodra 16 Haskell 平台 wxGTK 开发 GHHC 7 0 4 我正在尝试安装 wxHaskell 阴谋集团安装wx 然后给出这些错误 缺少对外国库的依赖 缺少 C 库 wx baseu 2 8 wx b
  • 处理 C++ 类中的惰性计算

    假设我有一堂课 class NumberCollection public typedef std set
  • 我可以从 GHCi 中找到 GHC 版本吗?

    gt 我在里面输入什么GHCi发现它正在使用哪个 GHC 版本 gt import System Info gt browse arch String compilerName String compilerVersion Data Ver
  • 如何让 esqueleto 为我生成 SQL 字符串?

    我怎样才能让esqueleto从a生成一个SQL字符串from陈述 的文档toRawSql说 你可以打开持久的查询日志记录 我尝试了所有可能的形式MonadLogger我可以理解 但它从未打印任何 SQL 同一文档还说 手动使用此功能 是可
  • 与 Functor 不同,Monad 可以改变形状?

    我一直很喜欢以下关于单子相对于函子的力量的直观解释 单子可以改变形状 函子不能 例如 length fmap f 1 2 3 总是等于3 然而 对于单子来说 length 1 2 3 gt gt g往往不等于3 例如 如果g定义为 g Nu
  • Haskell数据类型转换问题

    我目前正在学习 Haskell 并且一直在编写一些非常简单的程序来练习 我的程序之一是 import System IO main do putStrLn Give me year y lt getLine let res show cal
  • 这个实例有什么问题:ArrowApply Automaton?

    我希望 Automaton 有实例 ArrowApply 但 Control Arrow Transformer Automaton 没有 我认为下面的代码会表现良好 data Automaton b c Auto runAuto b gt
  • 如何与更高级别的类型合作

    玩弄教堂的数字 我遇到了无法指导 GHC 类型检查器处理高阶类型的情况 首先我写了一个版本 没有任何类型签名 module ChurchStripped where zero z z inc n z s s n z s natInteger
  • Haskell 为替代的 Either 数据类型定义 Functor 实例

    通过 Typeclassopedia 获得一些使用类型类的路由 想要替代Either的一个实例Functor 但即使检查定义Either作为一个例子Functor总是给我带来麻烦 有这个 但不会编译 data Alt a b Success

随机推荐