有没有办法强制GHC在特定值的生命周期内进行特定计算?
我显然可以将值放入记录中,为所述计算的结果创建惰性记录条目,并创建一个构建记录的制造商函数,并将值置于所述条目中.
我讨厌每次我想要它时都需要从记录中取出原始值.并且Haskell没有任何特殊的多态性 - 像C++或Java这样的关系.
是否有任何技巧可以在具有相同参数的函数的多个不相关调用中记忆值?
我可以模糊地想象各种形式的依赖类型的技巧,它们有效地告诉编译器多个用法即将到来.Haskell中没有任何依赖类型,但可能是隐式参数?我想不是,但我想我会问.也许是一个pragma?
想象一下,我有一个Necklace数据结构向量,我需要一个有理数的结果向量,存储为公分母和分子向量.
{-# LANGUAGE ImplicitParams #-}
import qualified Data.Vector as V
data Necklace = Necklace { ... }
necklace_length n = ...
denominator :: (necklaces :: V.Vector Necklace) => Int
denominator = V.foldl' lcm 30 $ V.map necklace_length ?necklaces
numerators :: (necklaces :: V.Vector Necklace) => V.Vector Int
numerators = V.map f ?necklaces
where f x = ... denominator ...
kittytoy :: (necklaces :: V.Vector Necklace) => Meow -> ...
kittytoy = …Run Code Online (Sandbox Code Playgroud) 随着算法的进展,我有一棵大树.每个节点都包含set,我认为它是作为平衡二叉搜索树实现的.在创建该节点的子节点之前,每个节点的集合在该节点创建之后应保持固定.
但我担心复制每一套都非常昂贵.相反,我希望每个新创建的节点集合利用父节点集合的所有适当部分.简而言之,我很高兴复制集合的O(log n)而不是O(n).
STL的关联数据结构是否有任何变体可以提供这种部分复制优化?也许在Boost?当然,在Haskell或OCaML中实现这样的数据结构是微不足道的,但是在C++中需要更多的努力.
GHC有什么工具,比如distcc吗?或者其他更原始的技巧来进行分布式编译?
我发现GHC对版本非常敏感.这是不切实际的,因为GHC还不支持交叉编译吗?
Rust std::ops::Index<T> 只支持T成为一个usize.这背后的原因是什么?
此外,当您尝试使用其他任何内容时,没有建议"尝试使用usize",只是"特质[&'static str]: core::ops::Index<u8>不满意"错误.这可能是因为他们计划支持更多类型T,但由于某种原因推迟这样做?
想象一下,我有一个名为libcat的C库,用于与我蓬松的猫进行交互.因此,我正在为OCaml编写绑定,以简化与蓬松的交互.
module type CAT = sig
type cat
val find : ... -> cat
val feed : cat -> unit
...
end ;;
module Cat : CAT = ...
Run Code Online (Sandbox Code Playgroud)
libcat中已经内置了相当多的内存管理,例如缓存,释放被破坏的玩具,甚至可能是用于清空垃圾的有限范围的垃圾收集器.然而,整体libcat要求用户明确地释放未使用的资源,例如丢失的玩具.
我为Cat.find编写了一个C存根,它使用libcat的cat_find例程查找并分配cat,但随后将结果指针存储到使用caml_alloc_custom创建的自定义块中的cat.
我在传递给caml_alloc_custom的custom_operations结构中添加了一个finalize方法.至关重要的是,我已经完成了这个最终确定方法,因为我在回答电话异常时,她厌倦了她在门上划伤.
我现在担心,如果OCaml复制了Cat.cat类型的自定义块,那么OCaml的垃圾收集器可能会在我们还在播放时释放蓬松.例如 :
let fluffy = Cat.find ;;
fluffy.yodel ;;
let meow = fluffy ;;
...
meow.feed ;;
Run Code Online (Sandbox Code Playgroud)
我们必须假设...在最后一次明确提到蓬松之后会触发OCaML的垃圾收集器,比如打破菜肴.这个垃圾收集活动是否会调用fluffy的finalize方法并释放她?或者只是简单地提到蓬松的原始定制块,从而防止蓬松被释放?
我想在这种情况下不会释放蓬松,否则OCaml肯定会在custom_operations结构中要求一个重复的方法,但我觉得最好问一下.如果实际上可以释放蓬松,我可以通过仅让OCaml通过引用来处理她来防止这种情况吗?粗略地说:
type cat_name = real_cat ref
type real_cat
Run Code Online (Sandbox Code Playgroud) 有人见过调用mlock(2)来防止 STL 容器的内容被交换到磁盘的分配器吗?
编写这样一个分配器只有一个棘手的部分,即通过对要 mlock 的分配进行集群来最小化 mlocked 页的数量。因此,人们可能应该从修改一些共享内存分配器开始?
我有兴趣推广使用Cayley Table的一些计算工具,这意味着基于查找表的乘法运算.
我可以创建一个最小的实现,如下所示:
date CayleyTable = CayleyTable {
ct_name :: ByteString,
ct_products :: V.Vector (V.Vector Int)
} deriving (Read, Show)
instance Eq (CayleyTable) where
(==) a b = ct_name a == ct_name b
data CTElement = CTElement {
ct_cayleytable :: CayleyTable,
ct_index :: !Int
}
instance Eq (CTElement) where
(==) a b = assert (ct_cayleytable a == ct_cayleytable b) $
ct_index a == ct_index b
instance Show (CTElement) where
show = ("CTElement" ++) . show . ctp_index
a …Run Code Online (Sandbox Code Playgroud) 我很好奇为什么C++没有定义void via:
typedef struct { } void;
Run Code Online (Sandbox Code Playgroud)
即无法实例化的类型中的值是什么,即使该安装必须不生成代码?
如果我们使用gcc -O3 -S,那么以下两个产生相同的汇编程序:
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
和
template <class T> T f(T a) { }
typedef struct { } moo;
int main() { moo a; f(a); return 0; }
Run Code Online (Sandbox Code Playgroud)
这很有道理.A struct { }只需要一个空值,很容易优化.事实上,奇怪的是,他们生成不同的代码-O3.
然而,你不能仅仅typedef void moo因为虚空无法承担任何价值,甚至不是空的价值.这种区别有没有用处?
还有其他各种强类型语言,比如Haskell,可能是MLs,它们的void类型有一个值,但是没有公开提供任何无价值的类型,尽管有些类型具有本机指针类型void *.
我很好奇Kiselyov和Shan 在" 功能性珍珠:隐式配置"一文中讨论的对隐式参数的反对意见.
在存在隐式参数的情况下内联代码(β-reduce)是不可靠的.
真?我希望GHC应该内联到与传递的隐式参数相同的范围,不是吗?
我相信我理解他们的反对意见:
如果添加,删除或更改其签名,则术语的行为可能会发生变化.
GHC的用户文档解释说,程序员必须注意多态递归和单态限制.这是不是因为内联问题意味着什么?
我假设这个多态递归示例还涵盖了"概括隐含参数"的意思吗?还要别的吗?
Data.Reflection的ReifiesStorable类型类是否真的是解决这些困难的合理解决方案?它似乎每次访问时都会对整个隐式数据结构进行反序列化,这听起来对性能来说是灾难性的.例如,我们可能希望我们的隐含信息是Cayley表或占用ram gig的字符表,并且必须在数百万代数运算期间访问.
是否有一些更好的解决方案采用隐式参数,或者编译器可以在幕后轻松优化的另一种技术,同时仍然通过类型系统使用状态线程或其他保证更多?
我发现mem::drop没有必要在它被调用的地方附近运行,这可能导致在昂贵的计算过程中保持Mutex或RwLock守卫.如何控制何时drop被调用?
作为一个简单的例子,我通过使用unsafe { ::std::intrinsics::drop_in_place(&mut s); }而不是简单地对密码材料工作的归零进行了以下测试::std::mem::drop(s).
#[derive(Debug, Default)]
pub struct Secret<T>(pub T);
impl<T> Drop for Secret<T> {
fn drop(&mut self) {
unsafe { ::std::intrinsics::volatile_set_memory::<Secret<T>>(self, 0, 1); }
}
}
#[derive(Debug, Default)]
pub struct AnotherSecret(pub [u8; 32]);
impl Drop for AnotherSecret {
fn drop(&mut self) {
unsafe { ::std::ptr::write_volatile::<$t>(self, AnotherSecret([0u8; 32])); }
assert_eq!(self.0,[0u8; 32]);
}
}
#[cfg(test)]
mod tests {
macro_rules! zeroing_drop_test {
($n:path) => {
let p : …Run Code Online (Sandbox Code Playgroud)