我正在通过Brent Yorgey的Haskell课程学习Haskell .我刚刚到达monad部分,虽然我认为我(最后)对如何使用monad有一个很好的把握,但我不明白如何测试使用它们的代码.
本节的练习是编写一个(简化的)风险模拟,它需要大量使用Rand StdGenmonad.特别是,我们必须编写以下函数:
type Army = Int
data Battlefield = Battlefield { attackers :: Army, defenders :: Army }
battle :: Battlefield -> Rand StdGen Battlefield
Run Code Online (Sandbox Code Playgroud)
这需要一个初始的战场,并模拟这场战斗将如何进行.
我有一个实现,但我不明白如何测试它.我无法"获取" Rand StdGen Battlefield返回的内部值battle,因此我无法在GHCI解释器中打印出来,这就是我到目前为止测试代码的方式.我也无法弄清楚如何在Haskell主函数或其他东西中打印战斗结果.人们如何测试这些功能?
我正在完成Brent Yorgey Haskell课程,而我在为Applicative定义一个好的实例时遇到了麻烦.解析器定义如下:
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
Run Code Online (Sandbox Code Playgroud)
该函数接受一个字符串,解析一定量的输入,并返回一个Maybe元组,其中第一个值是解析器的类型,其余的是未解析的字符串剩余部分.例如,这是正整数的解析器:
posInt :: Parser Integer
posInt = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit xs
Run Code Online (Sandbox Code Playgroud)
赋值是为Parser创建Applicative实例.我们从一个Functor实例开始(我认为这是相对简单的):
first :: (a -> b) -> (a,c) -> (b,c)
first f (a, c) = (f a, c)
instance Functor Parser where
fmap f p = Parser f'
where f' …Run Code Online (Sandbox Code Playgroud) 我正在写一个系统,我有一个Objects 的集合,每个Object都有一个唯一的整数ID.这是我在C++中如何做到这一点:
class Object {
public:
Object(): id_(nextId_++) { }
private:
int id_;
static int nextId_;
}
int Object::nextId_ = 1;
Run Code Online (Sandbox Code Playgroud)
这显然不是thread_safe,但如果我想要它,我可以创建nextId_一个std::atomic_int,或者在nextId_++表达式周围包装一个互斥.
我怎么做(最好是安全的)Rust呢?没有静态struct成员,全局可变变量也不安全.我总是可以nextId进入new函数,但是这些对象将被分配到很多地方,我宁愿nextId不管这个数字和yon.思考?
以下代码是否调用未定义的行为C?
int a = 1, b = 2;
a = b = (a + 1);
Run Code Online (Sandbox Code Playgroud)
我知道以下内容会调用UB:
a = b = a++;
Run Code Online (Sandbox Code Playgroud)
原因是它违反了标准中的以下条款:
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算来修改一次.此外,只能访问先前值以确定要存储的值.
但是,第一个代码段不违反此条款.一位同事说这种说法a = b = a+1也可能意味着
a = a + 1;
b = a + 1;
Run Code Online (Sandbox Code Playgroud)
要么
b = a + 1;
a = b;
Run Code Online (Sandbox Code Playgroud)
我认为,由于"从右到左"的相关性=,它总是必须意味着a = (b = (a+1)),而不是
a = a + 1;
b = a + 1;
Run Code Online (Sandbox Code Playgroud)
不过,我并不积极.是UB吗?
我正在尝试并行化我的算法.这是我将如何用C++编写它的草图:
void thread_func(std::vector<int>& results, int threadid) {
results[threadid] = threadid;
}
std::vector<int> foo() {
std::vector<int> results(4);
for(int i = 0; i < 4; i++)
{
spawn_thread(thread_func, results, i);
}
join_threads();
return results;
}
Run Code Online (Sandbox Code Playgroud)
这里的要点是每个线程都有一个它不拥有的共享可变对象的引用.在Rust中,这似乎很难做到.我是否应该尝试将它拼凑在一起(我猜这里)Mutex,Cell或者&mut,我应该遵循更好的模式吗?
是否可以使用boost :: geometry来检查两个线段(每个由2D中的两个点给出)是否相互交叉?如果可能的话,boost :: geometry是否也允许检查特殊情况,例如在另一条线上只有一个点(数字),或两条线是否相等?
我有一个算法,运行在我的双核,3 GHz英特尔处理器平均250毫秒,我正在尝试优化它.目前,我有一个std::nth_element呼叫,std::vector在150到300个元素之间调用大约6000次,平均需要50ms.我花了一些时间来优化我使用的比较器,它目前double从向量中查找两个并执行简单的<比较.比较器运行的时间可以忽略不计std::nth_element.比较器的拷贝构造函数也很简单.
由于此调用当前占用了我的算法的20%的时间,并且由于时间大部分花费在nth_element我没写的代码上(即不是比较器),我想知道是否有人知道优化的方法nth_element使用SIMD或任何其他方法?我已经看到了一些关于std::nth_element使用OpenCL和多线程进行并行化的问题,但由于这些向量很短,我不确定从这种方法中获得多少好处,尽管我很容易被告知我错了.
如果有SSE方法,我可以使用任何SSE指令(当前,我认为)SSE4.2.
谢谢!
这在C中合法吗?
struct Doubles
{
double a,b,c;
};
void foo(struct Doubles* bar)
{
double* baz = (double*)bar;
baz[0]++;
baz[1]++;
baz[2]++;
}
Run Code Online (Sandbox Code Playgroud)
我知道它在MSVC 2010上"有效",但我不知道它是否合法,或者不同的布局是否会导致UB.
我想制作一个单位向量的查找表。每个单位向量将映射到该表中的一个容器,并且该容器将包含具有相似方向的一小组向量的一些信息。
我可以轻松地使用 ($\theta$, $\phi$, 1) 表示向量,然后将角度范围切入容器以制作 2D 查找表(因此第一个容器是 0 到 $2* 范围内的 theta \pi / N$,其中 N 是我想要的 theta 方向的 bin 数量)。这样做的问题是,我认为某些箱将比其他箱代表单位球体表面上更大的区域,并且我希望获得大致相同大小的区域。
我认为均匀划分角度范围会使某些垃圾箱比其他垃圾箱更大,这是错误的吗?如果没有,有人知道制作这个查找表的更好方法吗?
我发现了一些像这样的论文和演示文稿,但我不会撒谎,我不明白它(我听说过勒贝格测度,但如果我知道它意味着什么,我会被诅咒的),而且它无论如何,看起来并不是特别有希望。
我采取的做法迅速几何箱子,我想实现两个结构,Vector以及Normal(这是因为标准的矢量和法向矢量地图通过一定的转换不同).我已经实现了以下特征:
trait Components {
fn new(x: f32, y: f32, z: f32) -> Self;
fn x(&self) -> f32;
fn y(&self) -> f32;
fn z(&self) -> f32;
}
Run Code Online (Sandbox Code Playgroud)
我也想将两个向量加在一起,以及两个法线,所以我有块看起来像这样:
impl Add<Vector> for Vector {
type Output = Vector;
fn add(self, rhs: Vector) -> Vector {
Vector { vals: [
self.x() + rhs.x(),
self.y() + rhs.y(),
self.z() + rhs.z()] }
}
}
Run Code Online (Sandbox Code Playgroud)
impl对于Normals 几乎完全相同.我真正想要的是Add impl为每个实现的结构提供一个默认值Components,因为通常它们都将以相同的方式添加(例如,第三个被调用的结构Point将执行相同的操作).是否有这样做除了用于写出三个相同实现的方式Point,Vector和Normal …
如果我有一个特征,我如何调用一个期望特征对象的函数Box<T>?换一种说法:
trait T { ... }
fn func(t: &T) { ... }
fn some_other_func() {
b: Box<T>; // Provided
// These work, but is there a better way?
func( &*b ); // 1
func( Borrow::borrow(&b) ); // 2
}
Run Code Online (Sandbox Code Playgroud)
1和2都错了.我错过了一些明显的东西吗
假设我在Rust中有以下结构:
struct Num {
pub num: i32;
}
impl Num {
pub fn new(x: i32) -> Num {
Num { num: x }
}
}
impl Clone for Num {
fn clone(&self) -> Num {
Num { num: self.num }
}
}
impl Copy for Num { }
impl Add<Num> for Num {
type Output = Num;
fn add(self, rhs: Num) -> Num {
Num { num: self.num + rhs.num }
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有以下代码片段:
let a = Num::new(0);
let b …Run Code Online (Sandbox Code Playgroud)