无论如何在Haskell中定义如下的函数?
or True True = True
or True undefined = True
or True False = True
or undefined True = True
or undefined False = undefined
or undefined undefined = undefined
or False True = True
or False undefined = undefined
or False False = False
Run Code Online (Sandbox Code Playgroud)
我目前没有它的用例(虽然我对它感兴趣),我只是感兴趣,如果可能的话.
Foldr Foldl Foldl页面讨论foldl'并定义如下:
foldl' f z [] = z
foldl' f z (x:xs) = let z' = z `f` x
in seq z' $ foldl' f z' xs
Run Code Online (Sandbox Code Playgroud)
这样做是为了避免空间泄漏,即fold'产生恒定大小的结果仅使用恒定空间.
但是,正如这里所指出的,这并不一定有效:
涉及的
seq函数只评估最顶层的构造函数.如果累加器是一个更复杂的对象,那么fold'仍然会建立未评估的thunk.
显而易见的解决办法是改变seq到deepseq如图所示(假设你正在使用NFData):
foldl_strict f z [] = z
foldl_strict f z (x:xs) = let z' = z `f` x
in deepseq z' $ foldl_strict f z' xs
Run Code Online (Sandbox Code Playgroud)
但我觉得这可能是非常低效的,因为整个结构需要deepseq通过循环每次遍历(除非编译器可以静态证明这不是必需的).
然后我尝试了这个:
foldl_stricter f z l …Run Code Online (Sandbox Code Playgroud) 我真的很喜欢Haskell,特别是它的强类型系统.当我得到Haskell程序进行编译时,它们通常没有bug,或者至少非常接近它.
然而,Haskell的主要问题是它未知的空间使用.至少在C++中,您可以相当确定程序的空间使用情况.当你构造和解构对象时,它是非常清楚的.
在Haskell中,如果你没有正确地编写它们,像折叠一样简单的东西可以在thunk中使用大量的空间.由于内存不足导致程序崩溃并没有比其他一些错误好得多,可以说更糟糕.
我知道有办法避免这些空间泄漏,但我正在寻找类型安全的方法来避免这些空间泄漏.就像在,如果我弄错了,我会得到某种编译错误,而不仅仅是希望我的程序在生产时崩溃.我很高兴例如,替换标准库函数(例如,如果它的累加器不严格,可能会说有编译错误的折叠)
Haskell中是否存在这样的事情?
让我们说具有如下通用代码:
y.hpp:
#ifndef Y_HPP
#define Y_HPP
// LOTS OF FILES INCLUDED
template <class T>
class Y
{
public:
T z;
// LOTS OF STUFF HERE
};
#endif
Run Code Online (Sandbox Code Playgroud)
现在,我们希望能够在我们创建的类(比如X)中使用Y. 但是,我们不希望X的用户必须包含Y标头.
所以我们定义了一个类X,如下所示:
x.hpp:
#ifndef X_HPP
#define X_HPP
template <class T>
class Y;
class X
{
public:
~X();
void some_method(int blah);
private:
Y<int>* y_;
};
#endif
Run Code Online (Sandbox Code Playgroud)
请注意,因为y_是指针,所以我们不需要包含它的实现.
实现在x.cpp中,它是单独编译的:
x.cpp:
#include "x.hpp"
#include "y.hpp"
X::~X() { delete y_; }
void X::someMethod(int blah) { y_->z = blah; }
Run Code Online (Sandbox Code Playgroud)
所以现在我们的客户可以只包含"x.hpp"来使用X,而不包括并且必须处理所有"y.hpp"标题:
main.cpp:
#include "x.hpp"
int main()
{ …Run Code Online (Sandbox Code Playgroud) 使用以下宏:
#define ASSERT_IF_TEMP(expr) static_assert(?, "Is temporary!");
Run Code Online (Sandbox Code Playgroud)
我该怎么做问号?
如果两个值相等,如果它们可以是除以下之外的空值,是否有更好的比较方法?
a = b or (a is null and b is null)
Run Code Online (Sandbox Code Playgroud) TVar如何运作?从我所看到的,它尝试在收到它们后立即运行所有事务,但是,事务完成使其他当前运行的事务无效,然后必须重新启动.这是TVar的工作原理吗?
如果是这种情况,如果每100ms发生1ms长的事务,这是否意味着需要200ms处理的事务永远不会完成?
我如何在Haskell中编写如下内容:
showSquare :: (Show a, Num a) => a -> String
showSquare x = "The square of " ++ (show x) ++ " is " ++ (show (x * x))
showSquare :: (Show a, not Num a) => a -> String
showSquare x = "I don't know how to square " ++ (show x)
Run Code Online (Sandbox Code Playgroud)
基本上,类似于C++中的boost :: enable_if.
GHC扩展是可以的.
考虑以下简单make_pair类:
template <class X, class Y>
struct Pair
{
X x;
Y y;
};
Run Code Online (Sandbox Code Playgroud)
此外,我们将制作一个简单的类来显示任何移动/副本:
struct C
{
C(int n_) : n(n_) {};
C(const C& x) { n = x.n; std::cout << "Copy: " << n << std::endl; }
C(C&& x) { n = x.n; std::cout << "Move: " << n << std::endl; }
int n;
};
Run Code Online (Sandbox Code Playgroud)
然后我们可以运行:
auto z1 = Pair<C, C>{C(1),C(2)};
Run Code Online (Sandbox Code Playgroud)
没有输出,C没有移动或复制.
但是,我们必须在构造函数中指定类型Pair.让我们说我们想推断这些.我们可以这样做:
template <class X, class Y>
Pair<X, Y> make_pair(X&& x, …Run Code Online (Sandbox Code Playgroud) 我有一种想法可以($)像通用一样Control.Category概括(.),我已经用这篇文章末尾的代码(也是ideone)完成了.
在这段代码中,我创建了一个名为的类FunctionObject.该类具有($)以下签名的函数:
($) :: f a b -> a -> b
Run Code Online (Sandbox Code Playgroud)
当然,我创建(->)了这个类的实例,因此$继续使用普通函数.
但是这允许你创建特殊的函数,例如,知道它们自己的逆,如下面的例子所示.
我总结说有三种可能性之一:
选项1似乎不太可能,我对hayoo的搜索没有显示选项2,所以我怀疑选项3是最有可能的,但如果有人可以解释为什么那就是好的.
import Prelude hiding ((.), ($))
import Control.Category ((.), Category)
class FunctionObject f where
($) :: f a b -> a -> b
infixr 0 $
instance FunctionObject (->) where
f $ x = f x
data InvertibleFunction a b =
InvertibleFunction (a -> b) …Run Code Online (Sandbox Code Playgroud)