我在业余时间学习Haskell已经有几个月了.我想知道Haskell如何在当前库存硬件上执行内存子系统(L1,L2,L3缓存).有人可以指点我关于缓存友好是Haskell的任何报告/研究,因为它的懒惰评估/按需调用?有没有办法让我们获取有关发生了多少数据缓存未命中和指令缓存未命中的信息,看看这是否是由于该语言的惰性评估性质?
谢谢.
Reddit上的一个人引起了我的注意:
main = do
let ns = [print 1, print 2, print 3]
sequence_ ns
sequence_ $ reverse ns
sequence_ $ tail ns ++ [head ns]
head ns
Run Code Online (Sandbox Code Playgroud)
这里发生的是我们有一系列操作,我们可以做的事情,如反向或得到它的尾巴或头部.
真棒.
我想要做的是进入单个元素并改变它们.例如,我希望能够做到这样的事情:
ns !! 0
Run Code Online (Sandbox Code Playgroud)
并获得类似[print,1]的内容,然后将最后一个元素更改为3.14,以便该函数将打印3.14.
在Haskell中是否可能,或者我应该回到LISP?
一个重要的编辑:我有点失误.我知道我需要创建一个新列表.是否有可能获得函数的参数,这是列表的一部分?我想要的是能够从它们的标识符/参数组成函数,并且能够在评估之前将函数分解为标识符/参数.
我似乎记得F#的旧版本允许在匹配序列时进行结构分解,就像列表一样.有没有办法在保持序列延迟的同时使用列表语法?我希望避免大量调用Seq.head和Seq.skip 1.
我希望有类似的东西:
let decomposable (xs:seq<'a>) =
match xs with
| h :: t -> true
| _ -> false
seq{ 1..100 } |> decomposable
Run Code Online (Sandbox Code Playgroud)
但这仅处理列表并在使用序列时给出类型错误.当使用List.of_seq时,它似乎会评估序列中的所有元素,即使它是无限的.
懒惰的线程安全单例实例对每个编码器来说都不容易理解,所以我想在我们的企业框架中创建一个可以完成这项工作的类.
你怎么看待这件事?你觉得它有什么坏处吗?在Apache Commons中有类似的东西吗?我怎样才能让它变得更好?
Supplier.java
public interface Supplier<T> {
public T get();
}
Run Code Online (Sandbox Code Playgroud)
LazyThreadSafeInstantiator.java
public class LazyThreadSafeInstantiator<T> implements Supplier<T> {
private final Supplier<T> instanceSupplier;
private volatile T obj;
public LazyThreadSafeInstantiator(Supplier<T> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
@Override
// http://en.wikipedia.org/wiki/Double-checked_locking
public T get() {
T result = obj; // Wikipedia: Note the usage of the local variable result which seems unnecessary. For some versions of the Java VM, it will make the code 25% faster and for others, it won't hurt.
if …Run Code Online (Sandbox Code Playgroud) 我需要找到一种方法如何清除我的应用程序存储在缓存中的数据.基本上我使用Fedor(在ListView中的图像的延迟加载)惰性列表实现,我想在我加载例如100个图像时自动清除缓存.任何想法怎么做?
编辑: 代码:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
list=(ListView)findViewById(R.id.list);
adapter=new LazyAdapter(this, mStrings);
list.setAdapter(adapter);
deleteCache(this);
adapter.notifyDataSetChanged();
}
public static void deleteCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new …Run Code Online (Sandbox Code Playgroud) 我偶然发现了Haskell和FP,并对这些可能性感到震惊.我内心的旧数学书呆子可以毫不费力地为实际有用的目的编写天真的代码.然而,尽管所有的阅读,我仍然很难理解如何不打出一些令人惊讶的性能瓶颈.
因此,我使用简单的实现编写了非常短的代码片段,然后尝试进行少量更改以查看性能如何响应.这里有一个我真的无法理解的例子......我写了这个函数,找到了约瑟夫斯问题的解决方案,目的是有一个天真的列表实现.
m = 3
n = 3000
main = putStr $ "Soldier #" ++ (show $ whosLeft [1..n]) ++ " survived...\n"
whosLeft [lucky] = lucky
whosLeft soldiers = whosLeft $ take (length soldiers -1) $ drop m $ cycle soldiers
Run Code Online (Sandbox Code Playgroud)
根据RTS,后者运行时间为190毫秒,生产率为63%.
然后我想要尝试的第一件事是删除(长度士兵-1)并用递减的整数替换它.
运行时间最长可达900毫秒,生产率降至16%,并且使用的内存比上述简单代码多47倍!所以我添加了严格的评估,强制使用Int类型,尝试删除全局变量等等,但没有多大帮助.我只是无法理解这种放缓.
m = 3::Int
n = 3000::Int
main = putStr $ "Soldier #" ++ (show $ whosLeft n [1..n]) ++ " survived...\n"
whosLeft 1 [lucky] = lucky
whosLeft n' soldiers = n' `seq` …Run Code Online (Sandbox Code Playgroud) performance haskell functional-programming lazy-evaluation josephus
我一直在想这个问题,但我找不到令人满意的答案.
为什么(++)"贵"?在惰性评估下,我们不会评估像这样的表达式
xs ++ ys
Run Code Online (Sandbox Code Playgroud)
在必要之前,即便如此,我们只会在需要时评估我们需要的部分.
有人可以解释我错过的东西吗?
什么是正确的范例或实用类(似乎找不到预先存在的类)来实现Java中的惰性供应商?
我希望有一些处理计算一次/缓存后行为的东西,并允许我独立指定计算行为.我知道这可能有错误,但它有正确的语义:
abstract public class LazySupplier<T> implements Supplier<T>
{
private volatile T t;
final private Object lock = new Object();
final public T get() {
if (t == null)
{
synchronized(lock)
{
if (t == null)
t = compute();
}
}
return t;
}
abstract protected T compute();
}
Run Code Online (Sandbox Code Playgroud) "R通过了承诺,而不是价值观.承诺在首次评估时被强制执行,而不是在通过时.",请参阅G. Grothendieck的回答.另请参阅Hadley的书中的这个问题.
在简单的例子中
> funs <- lapply(1:10, function(i) function() print(i))
> funs[[1]]()
[1] 10
> funs[[2]]()
[1] 10
Run Code Online (Sandbox Code Playgroud)
可以考虑这种不直观的行为.
但是,我发现自己经常在日常发展过程中陷入这个陷阱.我遵循一个相当功能的编程风格,这意味着我经常有一个函数A返回一个函数B,其中B在某种程度上取决于调用A的参数.依赖性不像上面的例子那么容易看,因为计算很复杂并且有多个参数.
忽略这样的问题导致难以调试问题,因为所有计算都顺利进行 - 除了结果不正确.只有对结果的明确验证才能揭示问题.
最重要的是,即使我注意到这样的问题,我也不确定我需要哪些变量,哪些变量不需要force.
我怎样才能确保不陷入这个陷阱?是否有任何编程模式可以防止这种情况,或者至少确保我发现存在问题?
F#中的Curried函数.我得到了一个位,传入一个参数子集产生一个带预设的函数.我只是想知道传递所有参数是否有任何不同.例如:
let addTwo x y = x + y
let incr a = addTwo 1
let added = addTwo 2 2
Run Code Online (Sandbox Code Playgroud)
incr是一个带有一个论点的函数.是addedint还是函数?我可以想象一个实现,其中"添加"仅在使用时被懒惰地评估(就像Schroedinger的Cat打开盒子一样).是否有保证何时进行添加?