我看到了this post在 hacker news今天。我正在努力解决同样的问题,即理解纯函数式编程将如何帮助我抽象出一个现实世界的问题。 7 年前,我从命令式编程转向了面向对象编程。我觉得我已经掌握了它,它对我很有帮助。在过去的几年里,我学到了一些函数式编程的技巧和概念,比如 map 和 reduce,我也喜欢它们。我已经在我的 OO 代码中使用了它们,并且对此很满意,但是在抽象一组指令时,我只能想到 OO 抽象来使代码更漂亮。
最近一直在研究python中的一个问题,一直在尽量避免使用OO来解决。在大多数情况下,我的解决方案看起来势在必行,而且我知道如果我使用 OO,我可以让它看起来既漂亮又干净。我想我会发布这个问题,也许功能专家可以提出一个既美观又实用的解决方案。如果必须,我可以发布我丑陋的代码,但宁愿不要。 :) 这里的问题:
用户可以请求图像或图像的缩略图。如果用户请求图像的缩略图,但它还不存在,请使用 python 的 PIL 模块创建它。还要使用人类可读的路径创建指向原始图像或缩略图的符号链接(symbolic link),因为原始图像名称是哈希码,而不是对其内容的描述。最后,重定向到该图像的符号链接(symbolic link)。
在 OO 中,我可能会创建一个 SymlinkImage 基类、一个 ThumbnailSymlinkImage 子类和一个 OriginalSymlinkImage 子类。共享数据(在 SymlinkImage 类中)将类似于原始路径。共享行为将创建符号链接(symbolic link)。子类将实现一个名为“generate”之类的方法,如果适用,该方法将负责创建缩略图,并调用其父类(super class)以创建新的符号链接(symbolic link)。
最佳答案
是的,你真的会使用函数式方法以非常不同的方式做到这一点。
这是使用类型化、默认纯函数式编程语言 Haskell 的草图.我们为您的问题的关键概念创建新类型,并将工作分解为一次执行一项任务的离散函数。 IO 和其他副作用(如创建符号链接(symbolic link))仅限于某些功能,并用类型指示。为了区分这两种操作模式,我们使用a sum type .
--
-- User can request an image or a thumbnail of the image.
-- If the user requests the thumbnail of the image, and it doesn't yet exist, create it using
-- python's PIL module. Also create a symbolic link to the original or
-- thumbnail with a human readable path, because the original image name is a
-- hashcode, and not descriptive of it's contents. Finally, redirect to the
-- symbolic link of that image.
--
module ImageEvent where
import System.FilePath
import System.Posix.Files
-- Request types
data ImgRequest = Thumb ImgName | Full ImgName
-- Hash of image
type ImgName = String
-- Type of redirects
data Redirect
request :: ImgRequest -> IO Redirect
request (Thumb img) = do
f <- createThumbnail img
let f' = normalizePath f
createSymbolicLink f f'
return (urlOf f)
request (Full img) = do
createSymbolicLink f f'
return (urlOf f)
where
f = lookupPath img
f' = normalizePath f
连同一些助手,我将把定义留给你。
-- Creates a thumbnail for a given image at a path, returns new filepath
createThumbnail :: ImgName -> IO FilePath
createThumbnail f = undefined
where
p = lookupPath f
-- Create absolute path from image hash
lookupPath :: ImgName -> FilePath
lookupPath f = "/path/to/img" </> f <.> "png"
-- Given an image, construct a redirect to that image url
urlOf :: FilePath -> Redirect
urlOf = undefined
-- Compute human-readable path from has
normalizePath :: FilePath -> FilePath
normalizePath = undefined
一个真正漂亮的解决方案是用一个数据结构抽象出请求/响应模型来表示要执行的命令序列。一个请求进来,构建一个结构纯粹是为了代表它需要完成的工作,然后交给执行引擎来完成诸如创建文件之类的事情。那么核心逻辑将完全是纯函数(不是这个问题有很多核心逻辑)。对于这种带有效果的真正纯函数式编程风格的示例,我推荐 Wouter Swiestra 的论文 ``Beauty in the Beast: A Functional Semantics for the Awkward Squad''。
关于functional-programming - 努力使用纯函数式编程来解决日常问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6190745/