gpt4 book ai didi

function - 在没有更高类型 (HKT) 支持的情况下,如何在 Rust 中创建通用结构?

转载 作者:行者123 更新时间:2023-11-29 07:55:22 24 4
gpt4 key购买 nike

我正在尝试使 Iteratee 结构通用,这样我就可以传入不同的解析函数并获得不同的 Iteratee。这是有效的非通用版本:

use std::io::{BufRead, BufReader};
use std::str::{from_utf8, Utf8Error};

#[derive(PartialEq, Debug)]
struct Cat<'a> {
name: &'a str,
}

fn parse<'a>(slice: &'a [u8]) -> Result<Cat<'a>, Utf8Error> {
from_utf8(slice).map(|name| Cat { name: name })
}

struct Iteratee<R>
where R: BufRead + Sized
{
read: R,
}

impl<R> Iteratee<R>
where R: BufRead + Sized
{
fn next<'a, F>(&'a mut self, fun: F)
where F: Fn(Option<Result<Cat<'a>, Utf8Error>>) -> () + Sized
{
let slice = self.read.fill_buf().unwrap();
fun(Some(parse(slice)))
// ^^^^^^^^^^^ How do I pull 'parse' up as a function of Iteratee
}
}

fn main() {
let data = &b"felix"[..];
let read = BufReader::new(data);
let mut iterator = Iteratee { read: read };
iterator.next(|cat| assert_eq!(cat.unwrap().unwrap(), Cat { name: "felix" }));
}

这是我尝试使其通用化的尝试,但我无法通过对函数的引用或传入闭包来构造 IterateeFun

struct IterateeFun<R, P, T>
where R: BufRead + Sized,
P: Fn(&[u8]) -> (Result<T, Utf8Error>) + Sized
{
read: R,
parser: P,
}

impl<R, P, T> IterateeFun<R, P, T>
where R: BufRead + Sized,
P: Fn(&[u8]) -> (Result<T, Utf8Error>) + Sized
{
fn next<'a, F>(&'a mut self, fun: F)
where F: Fn(Option<Result<T, Utf8Error>>) -> () + Sized
{
let slice = self.read.fill_buf().unwrap();
fun(Some((self.parser)(slice)))
}
}


fn main() {
let data = &b"felix"[..];
let read = BufReader::new(data);
let mut iterator = IterateeFun {
read: read,
parser: parse, // What can I put here?
// I've tried a closure but then I get error[E0495]/ lifetime issues
};

iterator.next(|cat| assert_eq!(cat.unwrap().unwrap(), Cat { name: "felix" }));
}

我想知道如何将函数传递到结构中,如图所示。或者我应该将此作为一种特质来代替吗?

最佳答案

与大多数问题一样,我只需要另一个间接级别!更高种类的类型 (HKT) 显然会有所帮助,但实际上我只需要能够将生命周期参数与我的解析函数相关联。

灵感来自用户 4815162342 和 Streamer我意识到我可以创建两个特征 Iteratee<'a>Parser<'a>每个都有一个关联类型,然后当我创建一个组合它们的实现时,我将能够组合关联类型以给我一种 HKT 形式:

trait Parser<'a> {
type Output: 'a;

fn parse(&self, &'a [u8]) -> Result<Self::Output, Utf8Error>;
}

struct CatParser;

impl<'a> Parser<'a> for CatParser{
type Output = Cat<'a>;

fn parse(&self, slice: &'a [u8]) -> Result<Self::Output, Utf8Error> {
parse(slice)
}
}

trait Iteratee<'a> {
type Item: 'a;

fn next<F>(&'a mut self, fun: F) where F: Fn(Option<Self::Item>) -> () + Sized;
}

struct IterateeParser<R, P> {
read: R,
parser: P,
}

impl<'a, R, P> Iteratee<'a> for IterateeParser<R,P> where R: BufRead + Sized, P: Parser<'a> {
type Item = Result<P::Output, Utf8Error>;
// ^^^^^^^^^ This is the magic!

fn next<F>(&'a mut self, fun: F) where F: Fn(Option<Self::Item>) -> () + Sized {
let slice = self.read.fill_buf().unwrap();
fun(Some(self.parser.parse(slice)))
}
}

fn main() {
let data = &b"felix"[..];
let read = BufReader::new(data);
let mut iterator = IterateeParser { read: read, parser: CatParser };
iterator.next(|cat| assert_eq!(cat.unwrap().unwrap(), Cat { name: "felix" }));
}

魔法线是type Item = Result<P::Output, Utf8Error>;

关于function - 在没有更高类型 (HKT) 支持的情况下,如何在 Rust 中创建通用结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41784344/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com