标签: lazy-evaluation

Haskell脚本耗尽空间

我正在使用项目Euler来自学Haskell,而且我在编写有关我的代码是如何被haskell执行时遇到了一些麻烦.第二个问题让我计算所有偶数斐波那契数的总和高达400万.我的脚本看起来像这样:

fibs :: [Integer]
fibs =  1 : 2 : [ a+b | (a,b) <- zip fibs (tail fibs)]

evens  :: Integer -> Integer -> Integer
evens x sum | (even x)   = x + sum
            | otherwise  = sum

main = do
  print (foldr evens 0 (take 4000000 fibs))
Run Code Online (Sandbox Code Playgroud)

Hugs给出错误"垃圾收集无法回收足够的空间",我认为这意味着列表条目不会因为它们被消耗而被释放foldr.

我需要做些什么来解决这个问题?我尝试编写一个使用累加器的尾递归(我认为)版本,但也无法使用它.

haskell space lazy-evaluation

2
推荐指数
2
解决办法
933
查看次数

haskell hFlush没有像我期待的那样工作

我正在尝试使用hFlush来读取整个文件的程序,以避免我遇到的与懒惰IO有关的问题.

readHandle <- openFile fileName ReadMode
hSetBuffering readHandle $ BlockBuffering (Just 2048)
fileText <- hGetContents readHandle
hFlush readHandle
hClose readHandle
Run Code Online (Sandbox Code Playgroud)

这只是给我错误:hFlush:非法操作(句柄关闭)

有人可以帮我理解发生了什么

io haskell lazy-evaluation

2
推荐指数
1
解决办法
256
查看次数

Ruby 2中的懒惰评估

我最近安装了Ruby 2.0.0,发现它现在有一个懒惰的方法用于Enumerable mixin.根据之前的函数式语言经验,我知道这可以提高代码的效率.

我做了一个懒惰与渴望的基准(不确定是否是没有实际意义),并发现懒惰持续更快.为什么是这样?什么使得懒惰评估更适合大输入?

基准代码:

#!/usr/bin/env ruby

require 'benchmark'

num = 1000
arr = (1..50000).to_a

Benchmark.bm do |rep|
    rep.report('lazy') { num.times do ; arr.lazy.map { |x| x * 2 }; end }
    rep.report('eager') { num.times do ; arr.map { |x| x * 2}; end }
end
Run Code Online (Sandbox Code Playgroud)

基准报告样本:

       user     system      total        real
lazy  0.000000   0.000000   0.000000 (  0.009502)
eager  5.550000   0.480000   6.030000 (  6.231269)
Run Code Online (Sandbox Code Playgroud)

ruby lazy-evaluation

2
推荐指数
1
解决办法
480
查看次数

Javascript懒惰评估斐波那契函数

之前我在Scala中使用延迟评估时提出了一个问题.我试图在Scala中编写以下Haskell函数:

fib a b = c : (fib b c)
   where c = a+b
Run Code Online (Sandbox Code Playgroud)

这个问题的答案是我不能使用Lists,而应该使用Streams.现在我想在Javascript中做同样的事情.我翻译了这个功能,并在这个网站上试了一下:

function fib(a,b) {
    c = a+b;
    return [c] + fib(b,c);
}

var res = fib(0,1).slice(0,10);

console.log(res);
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

RangeError: Maximum call stack size exceeded
Run Code Online (Sandbox Code Playgroud)

Javascript有办法做到这一点吗?

javascript haskell lazy-evaluation

2
推荐指数
1
解决办法
1506
查看次数

了解Haskell懒惰评估

原谅我的愚蠢问题,我是Haskell的新手.

我在Haskell中尝试了以下内容:

sum [fib n| n <- [1..], (even (fib n) && fib n < 4000000)] 
Run Code Online (Sandbox Code Playgroud)

这需要无限的时间.如果我遗漏n <- [1..],解决方案立即出现.

我认为这无关紧要,因为Haskell正在评估懒惰.我是否误解了懒惰的评价?

haskell fibonacci lazy-evaluation

2
推荐指数
2
解决办法
129
查看次数

使用闭包时,Swift延迟存储属性与常规存储属性

在Swift中,我们可以设置一个存储属性来使用闭包:

class Test {
  var prop: String = {
    return "test"
  }()
}
Run Code Online (Sandbox Code Playgroud)

VS

或者使懒惰的存储属性使用闭包:

class Test {
  lazy var prop: String = {
    return "test"
  }()
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,用于获取属性值的代码仅运行一次.看起来它们是等价的.

在使用闭包时,我应该何时使用延迟存储属性与计算属性?

closures lazy-evaluation swift

2
推荐指数
1
解决办法
1249
查看次数

后处理到Lazy-Sequences(Clojure)

假设我有一个叫做数字的懒惰序列给我一个无限的数字序列:0,1,2,3,4,5,6 ......

(def numbers (iterate inc 0))
Run Code Online (Sandbox Code Playgroud)

我通过将其传递给函数take来限制无穷大.例如:

(take 3 numbers)
; > (0 1 2)
Run Code Online (Sandbox Code Playgroud)

我问自己如何为懒惰序列的成员添加一些后处理.更具体地说:当我使用take时,如何声明一个产生以下输出的函数"numbers-doubled":

(take 3 numbers-doubled)
; > ("00" "11" "22")
Run Code Online (Sandbox Code Playgroud)

functional-programming clojure lazy-evaluation lazy-sequences clojurescript

2
推荐指数
1
解决办法
71
查看次数

优化惰性集合

这个问题是关于优化惰性集合的。我将首先解释问题,然后对可能的解决方案进行一些思考。问题以粗体显示

问题

Swift期望对Collections的操作为O(1)。一些操作中,特别是prefixsuffix样类型,偏离且为O(n)或更高的量级上。

延迟集合不能在初始化期间遍历基本集合,因为应该将计算尽可能长地延迟,直到实际需要该值为止。

那么,我们如何优化惰性集合?当然,这引出了一个问题,什么构成了优化的惰性集合?

思想

最明显的解决方案是缓存。这意味着第一次调用集合的方法具有不利的时间复杂度,但是随后可以在O(1)中计算对相同或其他方法的后续调用。为了更快的计算,我们将一些空间复杂度交易为O(n)的数量级。

尝试struct通过缓存优化s 上的惰性集合是不可能的,因为subscript(_ position:)您需要实现的所有其他方法都必须LazyProtocolCollection是non-,mutating并且structs默认是不可变的。这意味着我们必须为每次调用属性或方法重新计算所有操作。

这给我们留下了classes。类是可变的,这意味着所有计算的属性和方法都可以在内部改变状态。当我们使用类优化延迟集合时,我们有两个选择。首先,如果惰性类型的属性是variable,那么我们将自己带入一个充满痛苦的世界。如果更改属性,则可能会使先前缓存的结果无效。我可以想象管理代码路径以使属性可变为令人头疼的问题。其次,如果我们使用lets ,那么我们很好。初始化期间设置的状态无法更改,因此不需要更新缓存的结果。请注意,此处我们仅讨论的是带有纯方法且没有副作用的惰性集合。

但是类是引用类型。将引用类型用于惰性集合有什么弊端?Swift标准库不使用它们作为入门。

对不同的方法有什么想法或想法吗?

optimization lazy-evaluation swift

2
推荐指数
1
解决办法
378
查看次数

`if-then-else`(总是)可以用函数调用替换吗?

这个问题是关于PL如何工作的好奇心,而不是其他任何问题.(实际上,我看到的是SML,它与Haskell的不同之处在于前者使用call-by-value - 但我的问题是关于Haskell.)

Haskell(据我所知)有"按需调用"语义.这是否意味着如果我定义一个函数如下:

cond True thenExp elseExp = thenExp 
cond _ thenExp elseExp = elseExp
Run Code Online (Sandbox Code Playgroud)

这将总是表现得像if-then-else表达式?或者,在另一种意义上,if-then-else可以被视为可以被定义为函数的东西的语法糖?


编辑:

只是为了对比Haskell与Standard ML的行为,定义(在SML中)

cond p t f = if p then t else f;

然后是阶乘函数

fun factc n = cond (n=0) 1 (n * factc (n-1));

评估factc 1(说)永远不会完成,因为最后一个参数中的递归cond永远不会终止.

但是,定义

fun fact n = if n=0 then 1 else fact (n-1);

按预期工作,因为then分支仅根据需要进行评估.

也许有一些聪明的方法可以推迟SML中的参数评估(不知道我还不熟悉它)但重点是,在一个按值调用的类型语言中,if-then-else通常表现不同.我的问题是这是否(按需调用与按价值调用)是这种差异背后的主要原因(并且共识似乎是"是").

haskell lazy-evaluation

2
推荐指数
1
解决办法
260
查看次数

应用解析器陷入无限循环

我正在尝试实现自己的应用解析器,这是我使用的代码:

{-# LANGUAGE ApplicativeDo, LambdaCase #-}

module Parser where

-- Implementation of an Applicative Parser

import Data.Char
import Control.Applicative (some, many, empty, (<*>), (<$>), (<|>), Alternative)

data Parser a = Parser { runParser :: String -> [(a, String)] }

instance Functor Parser where
  -- fmap :: (a -> b) -> (Parser a -> Parser b)
  fmap f (Parser p) = Parser (\s -> [(f a, s') | (a,s') <- p s])

instance Applicative Parser where
  -- pure :: a -> …
Run Code Online (Sandbox Code Playgroud)

parsing haskell infinite-loop lazy-evaluation applicative

2
推荐指数
1
解决办法
102
查看次数