以下代码构建无限树,同时创建所有子树的缓存,以便不创建重复的子树.消除重复子树的基本原理来自对类似国际象棋游戏的状态树的应用:通过改变两个移动的顺序,人们通常可以最终处于相同的游戏状态.随着游戏的进行,无法访问的状态不应继续占用内存.我以为我可以通过使用弱指针来解决这个问题.不幸的是,使用弱指针将我们带入了IO Monad,这似乎已经破坏了足够/所有的懒惰,使得此代码不再终止.
因此我的问题是:是否有可能有效地生成一个没有重复子树的懒惰(游戏状态)树(并且没有泄漏内存)?
{-# LANGUAGE RecursiveDo #-}
import Prelude hiding (lookup)
import Data.Map.Lazy (Map, empty, lookup, insert)
import Data.List (transpose)
import Control.Monad.State.Lazy (StateT(..))
import System.Mem.Weak
import System.Environment
type TreeCache = Map Integer (Weak NTree)
data Tree a = Tree a [Tree a]
type Node = (Integer, [Integer])
type NTree = Tree Node
getNode (Tree a _) = a
getVals = snd . getNode
makeTree :: Integer -> IO NTree
makeTree n = fst <$> runStateT (makeCachedTree n) empty
makeCachedTree :: …Run Code Online (Sandbox Code Playgroud) tree haskell functional-programming weak-references infinite
有没有办法以类型安全的方式从枚举中随机选择一个元素?
我能找到的最好的方法是引入一个终结符值作为枚举的最后一个元素,这样你知道有多少个值,然后生成一个随机整数,在你投射到枚举的适当范围内.但是终结符值并不代表任何内容,因此您的枚举值无效,而且这不是类型安全的.在最新的C++标准中有更好的方法吗?
在Haskell中Data.Set实现了一个具体的集合类型.普通[]列表还实现了一组(in Data.List)的所有操作.但似乎没有Set他们都实现的预定义类型类.你可以自己实现一个:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}
module Set where
import qualified Data.List as ConcreteList
import qualified Data.Set as ConcreteSet
class Set set a | set -> a where
empty :: set
singleton :: a -> set
insert :: a -> set -> set
delete :: a -> set -> set
union :: set -> set -> set
intersection :: set -> set -> set
member :: a -> set -> Bool …Run Code Online (Sandbox Code Playgroud) 以下C++程序调用strtoul为负1.由于在任何无符号类型中都没有可表示负数,我原以为这会失败并返回0(如果无法执行有效转换,则返回零值.),而是大返回正数(如果读取的值超出unsigned long int的可表示值范围,则函数返回ULONG_MAX(定义<climits>),并errno设置为ERANGE.).
#include <cstdlib>
#include <iostream>
int main () {
{char s[] = "-1";
for (int b=0; b<17; ++b)
std::cout << "strtoul (unsigned) of " << s
<< " with base arg " << b
<< ": " << strtoul(s,0,b) << std::endl;}
}
Run Code Online (Sandbox Code Playgroud)
为什么strtoul没有失败并且为负数返回0?
data ConstrainedRecord a where
ConstrainedRecord :: Num a => { first :: a, second :: a }
Run Code Online (Sandbox Code Playgroud)
导致GHC抱怨"记录语法在这里是非法的".
该split_at_mut函数(用于在索引处拆分可变切片)需要实现不安全的代码(根据 Rust 书)。但书中也说:“借用切片的不同部分从根本上是可以的,因为两个切片不重叠”。
我的问题:为什么借用检查器不明白借用切片的不同部分从根本上是可以的?(是否有原因阻止借用检查器理解此规则,或者只是由于某种原因尚未实施?)
使用 Rust 1.48 尝试建议的代码仍然会导致书中显示的错误:
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = slice.len();
assert!(mid <= len);
(&mut slice[..mid], &mut slice[mid..])
}
fn main() {
let mut vector = vec![1, 2, 3, 4, 5, 6];
let (left, right) = split_at_mut(&mut vector, 3);
println!("{:?}, {:?}", left, right);
}
Run Code Online (Sandbox Code Playgroud)
给出错误信息:
error[E0499]: cannot borrow `*slice` as mutable more than once at a time
--> src/main.rs:6:30
|
1 | …Run Code Online (Sandbox Code Playgroud) FromStr和之间有什么真正的区别吗TryFrom<&str>?
从文档中的定义来看,一旦您替换 in ,它们看起来是&str相同T的TryFrom:
pub trait FromStr {\n type Err;\n fn from_str(s: &str) -> Result<Self, Self::Err>;\n}\n\npub trait TryFrom<T> {\n type Error;\n fn try_from(value: T) -> Result<Self, Self::Error>;\n}\nRun Code Online (Sandbox Code Playgroud)\n然后是解析:
\n\n\nfromStr\xe2\x80\x99s from_str 方法经常被隐式使用,通过 str\xe2\x80\x99s\nparse 方法。
\n
但是如果我们看看它的实现,我们会发现它除了提供稍微更短的调用方式之外没有做任何事情from_str:
pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {\n FromStr::from_str(self)\n}\nRun Code Online (Sandbox Code Playgroud)\n如果您查看 TryFrom 的库实现,那么它几乎完全由数字转换组成,尽管也有:
\nimpl<\'_, T, const N: usize> TryFrom<&\'_ [T]> for [T; N] where\n T: Copy, …Run Code Online (Sandbox Code Playgroud) 我想知道是否有一个标准函数迭代一个函数,该函数返回一个(Maybe值)超过一个初始值,收集列表中的值,但是当它到达Nothing时结束列表.这个功能可以像下面这样实现:
iterateMaybe f a = a : iterMaybe (f a) where
iterMaybe Nothing = []
iterMaybe (Just a) = a : iterMaybe (f a)
Run Code Online (Sandbox Code Playgroud)
或者略有不同:
iterateMaybe' f Nothing = []
iterateMaybe' f (Just a) = a : iterateMaybe' f (f a)
Run Code Online (Sandbox Code Playgroud)
文档中给出的示例unfoldr :: (b -> Maybe (a, b)) -> b -> [a]:
unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10
Run Code Online (Sandbox Code Playgroud)
可以使用冗余对轻松编写:
unfoldr (\b -> if b == 1 then Nothing else Just (b-1, b-1)) 11
Run Code Online (Sandbox Code Playgroud)
这对unfoldr需要什么(a,b)?为什么它的类型不是(a -> Maybe a) -> a -> [a]?
std::mem::swap有签名:
pub fn swap<T>(x: &mut T, y: &mut T)
Run Code Online (Sandbox Code Playgroud)
如果我尝试实现它(游乐场):
pub fn swap<T>(x: &mut T, y: &mut T)
Run Code Online (Sandbox Code Playgroud)
我收到有关两个参数的生命周期的错误:
pub fn swap<T>(a: &mut T, b: &mut T) {
let t = a;
a = b;
b = t;
}
Run Code Online (Sandbox Code Playgroud)
如果我将签名更改为:
error[E0623]: lifetime mismatch
--> src/lib.rs:4:9
|
1 | pub fn swap<T>(a: &mut T, b: &mut T) {
| ------ ------
| |
| these two types are declared with different lifetimes...
...
4 | b = t; …Run Code Online (Sandbox Code Playgroud)