这几天整理老硬盘,发现Windows-Explorer不支持对文件夹进行flatten操作,导致在处理许多事务时,显得很笨拙。
举个例子,
假定我有一个名叫gallery的文件夹,其结构如下:
其中有一个images子文件夹,里面有很多jpg图片:
现在我想把images里的jpg flatten到外面,变成这样:
这个操作在Windows-Explorer下显得很笨拙:
你需要先进入images目录 → 全选所有的图片 → 剪切 → 退回上一层目录 → 粘贴 → 删除images文件夹。
注意:这只是对于一个文件夹(2019-12-01)而已,考虑到批量操作(2019-12-01, 2019-12-02, 2019-12-03),更是麻烦的不行。。。
不知道你是否有发现:
这样的操作在日常工作中很常见(如果你没有发现,以后可以主动留心一下。至少以我个人而言,经常会使用到这样的操作),而它本质上是一个Monad(这或许也解释了为什么这样的操作会如此常见)。
下面简单说明它真的是一个Monad(并非严格证明,只是提出一些直观)
- 文件夹是一个Monad
文件夹支持两个操作:flatten 和 return
flatten 用于平坦一层文件夹(这个操作应作为文件管理器的内置功能)。用户可以在当前打开的文件夹窗口里通过快捷键实现一键flatten,也可以通过选择几个文件夹对它们同时做批量flatten。
比如:对2019-12-01这个文件夹使用flatten之后,其内部就变成1.jpg, 2.jpg, 3.jpg
return 用于包装文件或文件夹(这个操作应作为文件管理器的内置功能)。用户选择特定文件/文件夹后按下快捷键,即可再此之上再包一层文件夹。
- 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被解出)
- 如何处理文件夹和文件的类型unsound问题?
我们知道在windows系统中,一个文件夹里可以同时存放文件和文件夹。
比如:这样的目录结构是合法的:
然而,我们希望在一个文件夹里要么都是文件夹,要么都是文件(这就像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楼发现此法仍然有问题)。
- 如何处理 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。
- 文件夹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操作吗?
欢迎大家讨论。