Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 将IO映射到fp ts中任意一个的数组_Typescript_Fp Ts - Fatal编程技术网

Typescript 将IO映射到fp ts中任意一个的数组

Typescript 将IO映射到fp ts中任意一个的数组,typescript,fp-ts,Typescript,Fp Ts,有人能帮我弄清楚如何在fp ts中实现这一点吗 const$=cheerio.load'some text'; 常量测试=$'table tr'。获取 .maprow=>$row.find'a' .maplink=>link.attr'data-test'?link.attr'data-test':null .filterv=>v!=无效的 我也可以用task来完成所有的工作,但我不知道如何将它与IO混合,或者我根本不应该使用IO 这就是我到目前为止的想法: 常量选择器r=a:ChereIOSt

有人能帮我弄清楚如何在fp ts中实现这一点吗

const$=cheerio.load'some text'; 常量测试=$'table tr'。获取 .maprow=>$row.find'a' .maplink=>link.attr'data-test'?link.attr'data-test':null .filterv=>v!=无效的 我也可以用task来完成所有的工作,但我不知道如何将它与IO混合,或者我根本不应该使用IO

这就是我到目前为止的想法:

常量选择器r=a:ChereIOStatic:ChereIOSelector=>s:any,c?:any,r?:any=>as,c,r; const getElementText=text:string=>{ 回流管 IO.ofcheerio.load, IO.apIO.oftext, IO.mapselector, IO.mapx=>x‘表tr’, //我不知道在这里该做什么 ; } 更新: 我必须提到并澄清,对我来说,最具挑战性的部分是如何将输入从IO更改为一个或多个数组,然后过滤或忽略左边的,并继续执行任务或任务

TypeScript错误为类型“或”不可分配给类型“IO”


如果您想正确地执行此操作,那么您需要将所有非确定性非纯函数调用包装在IO或IO中,这取决于它们是否能够失败

首先让我们定义哪些函数调用是纯函数调用,哪些不是纯函数调用。我发现最容易想到的是这样的——如果函数总是为相同的输入提供相同的输出,并且不会引起任何可观察到的副作用,那么它是纯的

相同的输出并不意味着引用相等,它意味着结构/行为相等。因此,如果您的函数返回另一个函数,那么这个返回的函数可能不是同一个函数对象,但它的行为必须与原始函数相同,才能被视为纯函数

因此,在这些术语中,以下是正确的:

cherio.负载是纯的 美元是纯的 .得到不是纯粹的 .发现不是纯粹的 .attr不是纯的 地图是纯的 .过滤器是纯的 现在,让我们为所有非纯函数调用创建包装器:

const getIO = selection => IO.of(selection.get())
const findIO = (...args) => selection => IO.of(selection.find(...args))
const attrIO = (...args) => element => IO.of(element.attr(...args))
需要注意的是,这里我们在元素数组的包装版本中应用非纯函数.attr或attrIO。如果我们只是将属性映射到数组上,我们就得到了数组,但它不是非常有用,我们需要IO

因此,如果您有一个数组行,并且希望对其应用attrIO,则可以这样做:

import { array } from 'fp-ts/lib/Array';
import { io } from 'fp-ts/lib/IO';

const rows: Array<...> = ...;
// normal map
const mapped: Array<IO<...>> = rows.map(attrIO('data-test'));
// same result as above `mapped`, but in fp-ts way instead of native array map
const mappedFpTs: Array<IO<...>> = array.map(rows, attrIO('data-test')); 

// now applying traverse instead of map to "flip" the `IO` with `Array` in the type signature
const result: IO<Array<...>> = array.traverse(io)(rows, attrIO('data-test'));

现在,getTests将返回原始代码中测试变量中相同元素的IO

免责声明:我没有通过编译器运行代码,它可能有一些打字错误或错误。您可能还需要做出一些努力,使其全部为强类型

编辑:

若您想保留有关错误的信息(在这种情况下,其中一个a元素上缺少数据测试属性),那个么您有几个选项可以这样做。当前getTests返回一个IO。要在此处匹配错误信息,您可以执行以下操作:

IO—返回数组的IO,其中每个元素都是错误或值。要使用它,您仍然需要在以后进行过滤以消除错误。这是最灵活的解决方案,因为您不会丢失任何信息,但感觉也没用,因为在本例中,这两种方法都与string | null几乎相同。
如果您想正确地执行此操作,那么您需要将所有非确定性非纯函数调用包装在IO或IO中,这取决于它们是否能够失败

首先让我们定义哪些函数调用是纯函数调用,哪些不是纯函数调用。我发现最容易想到的是这样的——如果函数总是为相同的输入提供相同的输出,并且不会引起任何可观察到的副作用,那么它是纯的

相同的输出并不意味着引用相等,它意味着结构/行为相等。因此,如果您的函数返回另一个函数,那么这个返回的函数可能不是同一个函数对象,但它的行为必须与原始函数相同,才能被视为纯函数

因此,在这些术语中,以下是正确的:

cherio.负载是纯的 美元是纯的 .得到不是纯粹的 .发现不是纯粹的 .attr不是纯的 地图是纯的 .过滤器是纯的 现在,让我们为所有非纯函数调用创建包装器:

const getIO = selection => IO.of(selection.get())
const findIO = (...args) => selection => IO.of(selection.find(...args))
const attrIO = (...args) => element => IO.of(element.attr(...args))
需要注意的是,这里我们在元素数组的包装版本中应用非纯函数.attr或attrIO。如果我们只是将属性映射到数组上,我们就得到了数组,但它不是非常有用,我们需要IO

因此,如果您有一个数组行,并且希望对其应用attrIO,则可以这样做:

import { array } from 'fp-ts/lib/Array';
import { io } from 'fp-ts/lib/IO';

const rows: Array<...> = ...;
// normal map
const mapped: Array<IO<...>> = rows.map(attrIO('data-test'));
// same result as above `mapped`, but in fp-ts way instead of native array map
const mappedFpTs: Array<IO<...>> = array.map(rows, attrIO('data-test')); 

// now applying traverse instead of map to "flip" the `IO` with `Array` in the type signature
const result: IO<Array<...>> = array.traverse(io)(rows, attrIO('data-test'));

现在,getTests将返回原始代码中测试变量中相同元素的IO

免责声明:我没有通过编译器运行代码,它可能有一些打字错误或错误。您可能还需要做出一些努力,使其全部为强类型

编辑:

若您想保留有关错误的信息(在这种情况下,其中一个a元素上缺少数据测试属性),那个么您有几个选项可以这样做。当前getTests返回一个IO。要在此处匹配错误信息,您可以执行以下操作:

IO—返回数组的IO,其中每个元素都是错误或值。要使用它,您仍然需要在以后进行过滤以摆脱它 错误。这是最灵活的解决方案,因为您不会丢失任何信息,但感觉也没用,因为在本例中,这两种方法都与string | null几乎相同。
你不能用一个选择器吗?类似于$'table tr a[data test]'的东西您不能用一个选择器来完成吗?类似于$'table tr a[data test]'的东西非常好,谢谢你的回答。还有一件事我很好奇,那就是ioother,实际上我想我应该用它来跳过代码中的.filter部分。你能改进你的答案以涵盖这一部分吗?我想如果我们修改属性以返回IOI,两者都可以完成这项工作,我只是不知道如何将打字改回IOI更新了问题的这一部分。请看一看。谢谢这太有趣了!非常感谢您花时间解释多重方法。非常好,谢谢您的回答。还有一件事我很好奇,那就是ioother,实际上我想我应该用它来跳过代码中的.filter部分。你能改进你的答案以涵盖这一部分吗?我想如果我们修改属性以返回IOI,两者都可以完成这项工作,我只是不知道如何将打字改回IOI更新了问题的这一部分。请看一看。谢谢这太有趣了!非常感谢您花时间解释多重方法。
import * as Either from 'fp-ts/lib/Either';

const attrIO = (...args) => element: IO<Either<Error, string>> => IO.of(Either.fromNullable(new Error("not found"))(element.attr(...args) ? element.attr(...args): null));

const getTests = (text: string): IO<Either<Error, string>[]> => {
  const $ = cheerio.load(text);
  return pipe(
    $('table tr'),
    getIO,
    IO.chain(rows => array.traverse(io)(rows, flow($, findIO('a')))),
    IO.chain(links => array.traverse(io)(links, attrIO('data-test')))
  );
}
import * as Either from 'fp-ts/lib/Either';
import * as IOEither from 'fp-ts/lib/IOEither';

const { ioEither } = IOEither;

const attrIOEither = (...args) => element: IOEither<Error, string> => IOEither.fromEither(Either.fromNullable(new Error("not found"))(element.attr(...args) ? element.attr(...args): null));

const getTests = (text: string): IOEither<Error, string[]> => {
  const $ = cheerio.load(text);
  return pipe(
    $('table tr'),
    getIO,
    IO.chain(rows => array.traverse(io)(rows, flow($, findIO('a')))),
    IOEither.rightIO, // "lift" IO to IOEither context
    IOEither.chain(links => array.traverse(ioEither)(links, attrIOEither('data-test')))
  );
}
import { Monoid } from 'fp-ts/lib/Monoid';

type Result = { errors: Error[], values: string[] };

const resultMonoid: Monoid<Result> = {
  empty: {
    errors: [],
    values: []
  },
  concat(a, b) {
    return {
      errors: [].concat(a.errors, b.errors),
      values: [].concat(a.values, b.values)
    };
  } 
};

const attrIO = (...args) => element: IO<Result> => {
  const value = element.attr(...args);
  if (value) {
    return {
      errors: [],
      values: [value]
    };
  } else {
    return {
      errors: [new Error('not found')],
      values: []
  };
};

const getTests = (text: string): IO<Result> => {
  const $ = cheerio.load(text);
  return pipe(
    $('table tr'),
    getIO,
    IO.chain(rows => array.traverse(io)(rows, flow($, findIO('a')))),
    IO.chain(links => array.traverse(io)(links, attrIO('data-test'))),
    IO.map(results => array.foldMap(resultMonoid)(results, x => x))
  );
}