考虑以下Map
类型函数:
type Map :: (k1 -> k2) -> [k1] -> [k2]
type family Map f l where
Map _ '[] = '[]
Map f (x : xs) = f x : Map f xs
Run Code Online (Sandbox Code Playgroud)
然后我可以定义:
type MkPair a = (a, a)
Run Code Online (Sandbox Code Playgroud)
并尝试执行以下操作:
type Blah = Map MkPair [Int, Char]
Run Code Online (Sandbox Code Playgroud)
但我发现类型同义词不能部分应用。
但我可以做这个稍微迂回的路线:
type Mapper :: k1 -> k2 -> Type
data Mapper k1 k2 where
Mapper :: Type -> Mapper k1 k2
type MapF :: Mapper k1 k2 -> …
Run Code Online (Sandbox Code Playgroud) 我正在考虑开发一些命名参数代码,但它让我想到了一些如下代码:
#include <utility>
int main()
{
using std::make_pair;
auto x = make_pair(1, make_pair(2, make_pair(3, make_pair(4,5))));
}
Run Code Online (Sandbox Code Playgroud)
现在,一个天真的实现将首先执行"make_pair(4,5)",然后将结果复制到"make_pair(3,...)"的第二个元素中,然后将其复制到"make_pair"的第二个元素中(2,......)"等
不幸的是,这会导致O(n ^ 2)性能,并且会产生大量不必要的副本.我无法看到(命名)返回值优化如何帮助.
理想情况下,make_pair(4,5)
意识到它将在最后一个位置x
,并在那个地方构建自己.
更进一步:
#include <utility>
int main()
{
using std::make_pair;
auto&& x1 = make_pair(3, make_pair(4,5));
auto x2 = make_pair(1, make_pair(2, std::move(x1)));
}
Run Code Online (Sandbox Code Playgroud)
我也想避免像这样的代码中的副本.
这种优化是否如此明显以至于我应该假设编译器执行它或者是否有另一种方法我应该对其进行编码以避免副本?
我正在测试一些与重载IO运算符相关的C++代码.代码如下:
class Student {
private:
int no;
public:
Student(int n)
{
this->no = n;
}
int getNo() const {
return this->no;
}
friend istream& operator>>(istream& is, Student& s);
friend ostream& operator<<(ostream& os, const Student& s);
};
ostream& operator<<(ostream& os, const Student& s){
cout << s.getNo(); // use cout instead of os
return os;
}
istream& operator>>(istream& is, Student& s)
{
cin >> s.no; // use cin instead of is
return is;
}
Run Code Online (Sandbox Code Playgroud)
然而,内部的<<
和>>
,我可以使用:
ostream& operator<<(ostream& os, …
Run Code Online (Sandbox Code Playgroud) 假设我有一个包含三列的表key
,value
并且priority
在(key
,priority
)上有一个唯一键.
我想选择所有key
/ value
对,其中priority
该密钥高于任何其他优先级key
.
例如:
key | value | priority
----------------------
'a' | 'Alice' | 5
'a' | 'Aaron' | 10
'b' | 'Bob' | 1
Run Code Online (Sandbox Code Playgroud)
应该返回:
key | value
-------------
'a' | 'Aaron'
'b' | 'Bob'
Run Code Online (Sandbox Code Playgroud)
编写此类查询的有效方法是什么?
C++(或C++ 11)中的标准结构或库是否类似于a set
,但可能有多个key
.
即一组的std ::对可以由任一快速进行查找a
或b
.
所以你可以这样做:
std::string a = "hello";
std::string b = "world";
x.insert(a, b);
x.get<1>("hello") => std::pair("hello", "world"); // (fast lookup)
x.get<2>("world") => std::pair("hello", "world"); // (fast lookup)
Run Code Online (Sandbox Code Playgroud)
基本上就像一个带有两个索引的数据库表.
如果已经存在某些东西,我宁愿不重新发明轮子.
组合现有容器以使用此功能创建内容的简单方法也会很好.
可以说我有以下代码:
begin
select ... from T where x = 42; -- (1)
.
.
.
update T ... where x = 42; -- (2)
commit;
end;
Run Code Online (Sandbox Code Playgroud)
我是否正确地说,在时间(2)执行时,从(1)中的T中选择的任何内容可能不再在T中,例如,如果在另一个会话中执行以下操作:
delete from T where x = 42;
Run Code Online (Sandbox Code Playgroud)
如果是这样,我想要发生的是"锁定"的select语句T
,因此无法修改.
我意识到我可以通过以下方式明确地做到:
lock table T in exclusive mode;
Run Code Online (Sandbox Code Playgroud)
但如果T
是一种观点呢?我是否必须查看T
s视图/子视图的定义以查找它引用的所有表并单独锁定它们,或者我可以执行以下操作:
begin
START_TRANSACTION;
select ... from T where x = 42; -- (1)
.
.
.
update T ... where x = 42; -- (2)
commit;
end;
Run Code Online (Sandbox Code Playgroud)
Where START_TRANSACTION
确保锁定所有select语句中引用的所有表,直到事务完成为止?
或者是否有另一个更好的解决方案?如果这很重要,我正在使用Oracle 10g.
可以说我们有以下代码:
class C t where
g :: t
instance C Int where
g = 42
Run Code Online (Sandbox Code Playgroud)
简单.我们也可以在Int上定义函数,如下所示:
f1 :: Int -> Int
f1 x = x * x
Run Code Online (Sandbox Code Playgroud)
我一直在使用类型系列,特别是因为Data.Has
使用它们,我想将它们插入到IxSet
.
但在这里,我将提出一个简化的例子.让我们说我们想要定义一个X
类似于Int 的新类型.我们可以这样做:
type family X
type instance X = Int
Run Code Online (Sandbox Code Playgroud)
然后我们可以X
像这样定义函数:
f2 :: X -> X
f2 x = x * x + 1
Run Code Online (Sandbox Code Playgroud)
到目前为止没问题.现在让我们尝试定义一个实例C X
,就像我们为C Int
:
instance C X where
g = 43
Run Code Online (Sandbox Code Playgroud)
哦,现在我们有以下错误:
实例中的非法类型同义词族应用程序:
X
在实例声明中'C X' …
这是我在FIFO队列中的尝试:
type Queue a = [a] -> [a]
empty :: Queue a
empty = id
remove :: Int -> Queue a -> ([a], Queue a)
remove n queue = (take n (queue []), (\x -> drop n (queue x)));
add :: [a] -> Queue a -> Queue a
add elems queue = (\x -> queue (elems ++ x))
Run Code Online (Sandbox Code Playgroud)
empty
创建一个空队列,remove
获取队列的第一个n
元素并返回队列的其余部分作为元组的第二个元素,add
并将列表添加elems
到队列中.
这会O(1)
及时添加/删除1个元素和n个元素O(n)
吗?
如何写一个函数以便Left x
IO错误但是Right x
像往常一样返回结果,即函数有签名Either [Char] a -> IO a
?
基本上我希望Left err
结果成为err
IO Monad中的结果.
我可以写下面的内容:
f :: [Int] -> [Int]
f x = 0:(map (+1) x)
g :: [Int] -> [Int]
g x = map (*2) x
a = f b
b = g a
main = print $ take 5 a
Run Code Online (Sandbox Code Playgroud)
事情完美无缺(想象).
但是,假设我想做g
一些比2乘以更复杂的事情,比如向用户询问一个数字并添加它,如下所示:
g2 :: [Int] -> IO [Int]
g2 = mapM (\x -> getLine >>= (return . (+x) . read))
Run Code Online (Sandbox Code Playgroud)
那我怎么打结呢?
澄清:
基本上我希望Int
s 的列表f
是输入g2
,Int
s 的列表g2
是输入f
.