关于“当前主流操作系统的文件管理器是否缺少Monad操作”的一点思考

这几天整理老硬盘,发现Windows-Explorer不支持对文件夹进行flatten操作,导致在处理许多事务时,显得很笨拙。

举个例子,

假定我有一个名叫gallery的文件夹,其结构如下:

1

其中有一个images子文件夹,里面有很多jpg图片:

2

现在我想把images里的jpg flatten到外面,变成这样:

3

这个操作在Windows-Explorer下显得很笨拙:

你需要先进入images目录 → 全选所有的图片 → 剪切 → 退回上一层目录 → 粘贴 → 删除images文件夹。

注意:这只是对于一个文件夹(2019-12-01)而已,考虑到批量操作(2019-12-01, 2019-12-02, 2019-12-03),更是麻烦的不行。。。

不知道你是否有发现:

这样的操作在日常工作中很常见(如果你没有发现,以后可以主动留心一下。至少以我个人而言,经常会使用到这样的操作),而它本质上是一个Monad(这或许也解释了为什么这样的操作会如此常见)。

下面简单说明它真的是一个Monad(并非严格证明,只是提出一些直观)

  1. 文件夹是一个Monad

文件夹支持两个操作:flattenreturn

flatten 用于平坦一层文件夹(这个操作应作为文件管理器的内置功能)。用户可以在当前打开的文件夹窗口里通过快捷键实现一键flatten,也可以通过选择几个文件夹对它们同时做批量flatten。

比如:对2019-12-01这个文件夹使用flatten之后,其内部就变成1.jpg, 2.jpg, 3.jpg

return 用于包装文件或文件夹(这个操作应作为文件管理器的内置功能)。用户选择特定文件/文件夹后按下快捷键,即可再此之上再包一层文件夹。

  1. flatten 和 return 满足 Monad Law

unit law 把一个文件包起来放到另一个文件夹后flatten 等于 把这个文件夹本身包起来再flatten

associative law 先flatten每一个2019-12-01,2019-12-02,2019-12-03,...,再对gallery flatten 等于 先flatten gallery,再对其flatten的结果flatten(每一个images文件夹里的jpg被解出)

  1. 如何处理文件夹和文件的类型unsound问题?

我们知道在windows系统中,一个文件夹里可以同时存放文件和文件夹。

比如:这样的目录结构是合法的: 4

然而,我们希望在一个文件夹里要么都是文件夹,要么都是文件(这就像Haskell里,我们希望List里存放的元素的类型都是一样的)。

解决方法是:

把文件看成一种特殊的文件夹,一种co-induction type。换句话说,一个文件可以被无限flatten仍然是其本身而不会丢失信息。

这里说个题外话:

个人认为windows的文件夹同时能存放文件和文件夹是一种错误设计。

比如:我们可能会设计books这样的目录结构:

books\
 -- computer-science\csapp.pdf
 -- history\文明的冲突.pdf
 -- 甄嬛传.pdf

这里由于甄嬛传.pdf 没有被分类,它被放到了books的根下面。然而实际上,应该有一个名叫others的文件夹,所有未分类的文件都放到others下,而不是裸的放到books的根下(你们同意我这个观点吗?欢迎讨论)。

注: 根据2楼 LdBeth 的说法,Unix like system对该问题已有更好的解决方案(39楼发现此法仍然有问题)。

  1. 如何处理 flatten 之后同名文件/文件夹的replacemenet问题?

说实话,这是个比较严重的问题,并且windows对于copy-paste的replacement机制做的不是很好。

举个例子:

假设我从网站1下载了1000张图片到A文件夹,从网站2也下载了1000张图片到B文件夹,这2000张图片里有一部分图片是重名的。然后,我全选B中的文件copy-paste到A里去。通常来讲,我所期待的行为是对于那些重名的文件,只保留高清图片。

对于这种情况,windows的copy-paste的replacement机制完全不适用,因为当文件名发生冲突时windows只会提示出3个选项:替换、跳过、保留两份, 它无法根据图片的大小来自动取舍(你往往需要写脚本或借用别的软件来解决这方面的问题)。

一个好的文件夹管理器应该能支持用户自定义。

这里唯一的问题是:是否需要支持让用户写脚本来决定replacement?

如果要支持脚本,则系统必须提示出警告要求用户所提供的脚本操作必须满足Monoid。

比如:根据文件大小来决定就是Monoid,因为基于Number的Maximum/Minimum是一个Monoid(但是使用文件大小的差值来做比较是不允许的)

另一种方法是:只提供基于文件属性的几个固定操作来做比较(比如:文件大小、日期等),用Haskell表达就是这些属性必须属于Ord。

  1. 文件夹Monad 和 List/Set Monad 的区别?

文件夹Monad不同于List Monad:

因为文件夹Monad需要处理同名文件,List Monad不需要

文件夹Monad不同于Set Monad:

因为Set Monad 里 element有名字,set没有名字,但是在文件夹Monad里,文件名有名字,文件夹也有名字。同名的文件夹也需要递归merge。

然而,即使文件夹Monad 和 List/Set Monad 有诸多的不同,但是它仍然是一个合法Monad。


以上是我这几天的思考,希望抛砖引玉。

未来操作系统的文件管理器应该加入Monad操作吗?

欢迎大家讨论。

挺有意思的。不过“文件夹是monad”这句话有点奇怪。任何东西只要提供了monad那几个操作都可以是monad。提供不同的操作还可以是不同的monad。

lens 了解一下。

然而实际上,Unix like file system 有一个叫 . 的文件夹。你可以把 /foo/bar/1.jpg 当做 /foo/bar/./1.jpg 的语法糖。

1 个赞

其实分类的话我倾向于用tag。tag可以有多个,搜索的时候可以组合起来过滤,文件夹一个文件夹只能有一个。当然你可以硬链接,但是搜索还是比较麻烦

Lens 在这里能解决什么问题呢?

解決了 po 主还沒想好这个 monad 该叫什么的问題

Lens 跟 Monad 叫什么有什么关系?

FS的上层不是一个tree/map 结构?怎么就成了monad?

这里主要是指支持flatten和return这两个操作的文件夹是一个Monad。

显然在windows下没有提供这两个原生操作,所以当遇到类似情况的时候,需要人肉来完成。

请问下,你说的lens具体指什么?(有支持这样操作的文件管理器吗)

我只知道Haskell有一个lens库。

free monad is a tree :slight_smile:

说人话就是,滿足 Monad 性质的最小结构就是 tree。

Lens到底是啥?

不懂就问:Maybe 是 monad 吗?Maybe 和 Tree 谁「小」?

我猜你想对 flattern 以后的 List 做操作,然后 map 回原來的 file hierarchy。

Maybe也是tree吧

非常不准确的概括:给可怜的函数式用户们的 getter / setter

对Unix like file system不是很了解。

不过这确实很棒!不需要再把文件看成co-induction类型的文件夹了(已修改原文增加了这一条)

因为所有裸文件自动被单独打成了一个文件夹(实际上这也是我最初期望的type sound机制,没想到unix like file system已经实现)

你是不是没有用过cmd?Windows没有...

“type sound” 不需要限制文件夹和文件不能混合着放吧。

data FileT = Folder [FileT] | File 这样是不是也可以?

这里是为什么呢?