我是函数式编程的新手,现在学习Haskell.作为练习,我决定实现一维线性扩散方程的显式欧拉方法.虽然下面的代码工作正常,但我对它的性能并不满意.事实上,我关心的是内存消耗.我相信它与懒惰评估有关,但无法弄清楚如何减少其内存使用量.
算法的想法非常简单,用命令性的术语表达:它采用一个"数组",并且每个内部点都添加一个值,该值是作为点本身和其中的值的组合计算的.邻居.边界点是特殊情况.
所以,这是我的Euler1D.hs模块:
module Euler1D
( stepEuler
, makeu0
) where
-- impose zero flux condition
zeroflux :: (Floating a) => a -> [a] -> [a]
zeroflux mu (boundary:inner:xs) = [boundary+mu*2*(inner-boundary)]
-- one step of integration
stepEuler :: (Floating a) => a -> [a] -> [a]
stepEuler mu u@(x:xs) = (applyBC . (diffused mu)) u
where
diffused mu (left:x:[]) = [] -- ignore outer points
diffused mu (left:x:right:xs) = -- integrate inner points
(x+mu*(left+right-2*x)) : diffused mu (x:right:xs)
applyBC inner …Run Code Online (Sandbox Code Playgroud) garbage-collection haskell functional-programming memory-management lazy-evaluation
假设我有一个非常大的数字(数百万/十亿+)这些简单的Foo数据结构:
data Foo = Foo
{ a :: {-# UNPACK #-}!Int
, b :: Int
}
Run Code Online (Sandbox Code Playgroud)
随着这么多的浮动,有必要考虑他们消耗多少内存.
在64位机器上,每个Int都是8个字节,因此a只需要8个字节(因为它是严格的和解压缩的).但是会b占用多少内存?我想这会根据thunk是否被评估而改变,对吧?
我想在一般情况下这是不可能的,因为b可能依赖于任何数量的内存位置,只有在b需要评估的情况下才会留在内存中.但是,如果b只依赖(一些非常昂贵的操作)a呢?那么,是否有一种确定性的方式来判断将使用多少内存?
我想从带有动态过滤器的sql server中提取一些数据.我正在以下列方式使用伟大的R包dplyr:
#Create the filter
filter_criteria = ~ column1 %in% some_vector
#Connect to the database
connection <- src_mysql(dbname <- "mydbname",
user <- "myusername",
password <- "mypwd",
host <- "myhost")
#Get data
data <- connection %>%
tbl("mytable") %>% #Specify which table
filter_(.dots = filter_criteria) %>% #non standard evaluation filter
collect() #Pull data
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常但现在我想以某种方式在我的表的所有列上循环它,因此我想将过滤器编写为:
#Dynamic filter
i <- 2 #With a loop on this i for instance
which_column <- paste0("column",i)
filter_criteria <- ~ which_column %in% some_vector
Run Code Online (Sandbox Code Playgroud)
然后使用更新的过滤器重新应用第一个代码.
不幸的是,这种方法没有给出预期的结果.实际上它没有给出任何错误,但是甚至没有将任何结果拉入R.特别是,我看了两个代码生成的SQL查询,并且有一个重要的区别.
第一个工作代码生成表单的查询:
SELECT ... FROM …Run Code Online (Sandbox Code Playgroud) 首先,让我为那些不认识的人定义什么是捷径融合.在JavaScript中考虑以下数组转换:
var a = [1,2,3,4,5].map(square).map(increment);
console.log(a);
function square(x) {
return x * x;
}
function increment(x) {
return x + 1;
}Run Code Online (Sandbox Code Playgroud)
这里我们有一个数组,[1,2,3,4,5]其元素首先被平方,[1,4,9,16,25]然后递增[2,5,10,17,26].因此,虽然我们不需要中间数组[1,4,9,16,25],但我们仍然创建它.
捷径融合是一种优化技术,它可以通过将一些函数调用合并为一个来消除中间数据结构.例如,可以将快捷融合应用于上述代码以产生:
var a = [1,2,3,4,5].map(compose(square, increment));
console.log(a);
function square(x) {
return x * x;
}
function increment(x) {
return x + 1;
}
function compose(g, f) {
return function (x) {
return f(g(x));
};
}Run Code Online (Sandbox Code Playgroud)
如您所见,通过组合和函数将两个单独的map调用融合到一个map调用中.因此,不创建中间阵列.squareincrement
现在,我理解像Immutable.js和Lazy.js这样的库在JavaScript中模仿延迟评估.延迟评估意味着仅在需要时计算结果. …
人们认为Haskell在并行性方面具有优势,因为它具有不变的数据结构。但是Haskell也很懒。这意味着实际上可以将数据从thunk突变为评估结果。
因此,懒惰似乎会损害不变性的优势。我是错的还是Haskell有针对此问题的对策?还是这是Haskell的特色?
如何在Ruby中获取一个惰性数组?
在Haskell中,我可以谈论[1..],这是一个无限的列表,根据需要懒洋洋地生成.我也可以做类似的事情iterate (+2) 0,它应用我给它的任何函数来生成一个惰性列表.在这种情况下,它会给我所有偶数.
我确信我可以在Ruby中做这些事情,但似乎无法弄清楚如何.
今天,当在存在的GADT构造函数上进行匹配时,尝试使用延迟模式时出现编译器错误:
存在或GADT数据构造函数不能在惰性(〜)模式中使用
为什么会有这种限制?如果被允许,会发生什么"坏"的事情?
haskell pattern-matching lazy-evaluation existential-type gadt
未装箱的类型,比如Int#,和严格的功能,f (!x) = ...是不同的,但我看到概念上的相似性 - 他们在某种程度上不允许暴力/懒惰.如果Haskell是像Ocaml这样的严格语言,那么每个函数都是严格的,并且每个类型都是未装箱的.unboxed类型与强制执行之间的关系是什么?
我喜欢Clojure.困扰我的一个问题是我不知道如何实现懒惰的序列,或者它们是如何工作的.
我知道懒惰序列只评估序列中要求的项目.它是如何做到的?
在Haskell中,我可能会这样实现if:
if' True x y = x
if' False x y = y
spin 0 = ()
spin n = spin (n - 1)
Run Code Online (Sandbox Code Playgroud)
这表现我的期望:
haskell> if' True (spin 1000000) () -- takes a moment
haskell> if' False (spin 1000000) () -- immediate
Run Code Online (Sandbox Code Playgroud)
在Racket中,我可以实现这样的缺陷if:
(define (if2 cond x y) (if cond x y))
(define (spin n) (if (= n 0) (void) (spin (- n 1))))
Run Code Online (Sandbox Code Playgroud)
这表现我的期望:
racket> (if2 …Run Code Online (Sandbox Code Playgroud) evaluation haskell lazy-evaluation expression-evaluation idris
lazy-evaluation ×10
haskell ×6
evaluation ×2
clojure ×1
dplyr ×1
gadt ×1
idris ×1
immutability ×1
immutable.js ×1
javascript ×1
lazy.js ×1
lisp ×1
r ×1
ruby ×1
strictness ×1
thunk ×1