首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拥有ramda和ramda的一元IO -幻想

拥有ramda和ramda的一元IO -幻想
EN

Stack Overflow用户
提问于 2016-10-05 23:10:17
回答 1查看 1.2K关注 0票数 5

想弄清楚IO单子是怎么工作的。

使用下面的代码,我读取filenames.txt并使用结果重命名testfiles目录中的文件。这显然是未完成的,因此,与其实际上重命名任何我记录到控制台的内容。:)

我的问题是:

  1. 我给runIO打了两次电话,但觉得应该只打一次电话,最后呢?
  2. 我想使用renameIO而不是renaneDirect,但是找不到合适的语法。

任何其他的建议也是非常感谢的,我是新的FP!

代码语言:javascript
复制
    var R = require('ramda');
    var IO = require('ramda-fantasy').IO
    var fs = require('fs');

    const safeReadDirSync = dir => IO(() => fs.readdirSync(dir));
    const safeReadFileSync = file => IO(() => fs.readFileSync(file, 'utf-8'));

    const renameIO = (file, name) => IO(() => console.log('Renaming file ' + file + ' to ' + name + '\n'));
    const renameDirect = (file, name) => console.log('Renaming file ' + file + ' to ' + name + '\n');

    safeReadFileSync("filenames.txt") // read future file names from text file
            .map(R.split('\n')) // split into array
            .map(R.zip(safeReadDirSync('./testfiles/').runIO())) // zip with current file names from dir
            .map(R.map(R.apply(renameDirect))) // rename
            .runIO(); // go!
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-06 00:28:22

你离解决方案不远了。

也可以避免对runIO的第二次调用,您可以利用Ramda中的IO类型实现来自幻想世界规范的Apply接口这一事实。这允许您解除一个函数(如您的renameDirect),以接受IO类型的参数,并将该函数应用于IO实例中包含的值。

我们可以在这里使用R.ap,它有IO (a -> b) -> IO a -> IO -> b的签名(这里专门用于IO)。这个签名表明,如果我们有一个IO实例,它包含一个接受某种类型a并返回某种类型b的函数,以及另一个包含某种类型aIO实例,那么我们可以生成一个包含某种类型bIO实例。

在我们讨论这一点之前,我们可以通过将R.zipR.apply(renameDirect)结合起来,对R.zipWith(renameDirect)的使用做一些细微的更改。

现在,您的示例现在可以如下所示:

代码语言:javascript
复制
var R = require('ramda')
var IO = require('ramda-fantasy').IO
var fs = require('fs')

const safeReadDirSync = dir => IO(() => fs.readdirSync(dir));
const safeReadFileSync = file => IO(() => fs.readFileSync(file, 'utf-8'))
const renameDirect = (file, name) => console.log('Renaming file ' + file + ' to ' + name + '\n')

const filesIO = R.map(R.split('\n'), safeReadFileSync('filenames.txt'))
const testfilesDirIO = safeReadDirSync('./testfiles/')

const renameDirectIO = (files, names) =>
  R.ap(R.map(R.zipWith(renameDirect), files), names)

renameDirectIO(testfilesDirIO, filesIO).runIO()

在本例中,我们在这里通过调用IO (a -> b)创建了一个R.zipWith(renameDirect)实例,该实例将部分应用R.zipWith(renameDirect)中存储在files中的值。然后将它与names值一起提供给names,它将生成一个新的IO实例,该实例包含与IO(() => R.zipWith(renameDirect, value.runIO(), names.runIO())等效的内容的有效结果。

现在,由于必须调用R.map部分应用于R.ap的第一个参数,所以有另一个助手函数R.lift可能对此有用,它负责提升给定函数以生成一个现在接受Apply实例的新函数。

所以在上面的例子中:

代码语言:javascript
复制
const renameDirectIO = (files, names) =>
  R.ap(R.map(R.zipWith(renameDirect), files), names)

可简化为:

代码语言:javascript
复制
const renameDirectIO = R.lift(R.zipWith(renameDirect))
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39885055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档