在Clojure / Haskell中管理不变量

我一直在比较面向对象和面向对象的方法,而且我不能在功能编程中把我的头放在一件事上 - 在数据结构中保持不变。

例如,想象下面的要求。

我们有一个项目清单,每个项目都有一个任务清单和一个分配成员清单。 每个任务都可以分配一个工作人员,但只能从项目分配成员列表中分配。

我可以想象,如何通过添加所需的检查和异常来在OOP语言中解决此问题(例如在Java中),这将导致我认为更强大的代码。

但是,由于数据与FP中的行为分离,我应该如何解决FP中的相同问题,比如在Clojure或Haskell中?


你的问题是非常普遍的,很多策略可以用来解决相关的问题,但本质上,检查不变量(在运行时)与OOP中的“相等”

assign :: Task -> Worker -> Either String Task
assign task worker =
    if not (taskProject task) `containsWorker` worker
        then Left "You can't assign..."
        else Right $ task { taskWorkers = worker : taskWorkers task }

一种常见的行为是隐藏data构造函数(如TaskWorkerProject ),OOP对象编写private构造函数。

module Scheduler (
  Task   -- instead `Task (..)`
, Worker -- instead `Worker (..)`
...
, assign
, createTask
, createWorker
...
) where

(我不知道当前Haskell支持给friendprotected ,...对手可能不存在,你可以找到很多Haskell模块与Some.Module.Internals.Something与私人对象)

主要问题是如何构建整个程序以实现所需的行为。

真实世界Haskell是了解这一点的最佳起点,或者如相关问题所建议的那样Haskell中的大规模设计?

另一方面,关于Haskell中的前/后条件,您可以阅读Haskell中的前提条件检查的选项。


在Clojure中,可以在任何函数上指定任意:pre:post条件。 以下是文档中的一个示例:

(defn constrained-sqr [x]
    {:pre  [(pos? x)]
     :post [(> % 16), (< % 225)]}
    (* x x))

还有一个非常有趣的图书馆核心。在Clojure中实施契约的合同。


你说数据与FP语言中的行为是“分离的”,但是在Haskell中(我不知道Clojure),你可以很容易地在模块中定义数据结构,使其定义保密,并且只导出函数来操纵数据。

换句话说,Haskell没有(OO风格)类,但它仍然具有封装性。

链接地址: http://www.djcxy.com/p/42877.html

上一篇: Managing invariants in Clojure / Haskell

下一篇: Best Practice on design and usage of data type in Haskell