2011-11-09 46 views
2

来自OOP我最近几周开始阅读函数式编程,并开始学习Haskell。我经常读到,(纯粹的)函数更容易测试,因为没有复杂的设置和拆卸例程。这听起来很合理,我同意了。通过编写这些函数,我可以通过一个经过良好测试的“基础”构建更复杂的函数。将数据类型传递给函数vs oop方法调用

当我盯着写我的第一个程序的一些功能得到了越来越多的参数,所以我开始创造出对我来说是类似结构的新的数据类型。当然,数据类型捆绑了逻辑上属于什么,有时由其他数据类型组成。然后

调用的功能,如

MyTpye = foo(MyTpye, someParam) 

感觉有点像在结构与函数指针实现面向对象编程与真难看的语法早在C的时代:

MyType = foo(this, someParam) = { 
    ... 
    return modified_copy_of_this; 
} 

测试这些功能也要求我首先设置我的新数据类型,这可能很复杂,我只是觉得我赢不了太多。

我想我还是太狭隘,专注于编写代码的OOP方式。我只是觉得在数据类型上调用函数只是调用不可变对象上的方法(当然,每个设置器都必须返回对象的修改版本)。

有人可以为我澄清这一点点吗?

非常感谢!

我加了这个Haskell的例子。这些是我的第一步,我试图发布这样丑陋的代码。 这只是再形成阶段学习算法的第一部分。建立一个具有可用状态,行为和奖励功能的“环境”。

type Action = [Double] 
type State = [Double] 

data StateSet = StateSet [State] deriving (Show) 
data ActionSet = ActionSet [Action] deriving (Show) 

data Environment = Environment { 
    availableStates :: StateSet, 
    availableActions:: ActionSet, 
    currentState :: State, 
    rewardfnc  :: State -> Action -> Double, 
    lastReward  :: Double 
} 

rewardFunction :: State -> Action -> Double 
rewardFunction s a = (-1) 

doAction :: Environment -> Action -> Environment 
doAction env a = Environment (availableStates env) (availableActions env) a (rewardfnc env) ((rewardfnc env) (currentState env) a) 

getReward :: Environment -> Double 
getReward env = (lastReward env)  

states = StateSet [[i,j] | i <- [1..10], j <- [1..10]] 
actions = ActionSet [[i,j] | i <- [1..10], j <- [1..10]] 

initEnv = Environment states actions [0,0] rewardFunction 0.0 
env = doAction initEnv [2,2] 
reward = getReward(env) 
+1

你能否给一个更具体的例子(最好在Haskell中,因为这就是你想学的东西)?我发现这个例子没有任何问题(如果我将它读作伪代码)。也许你可以提供你的类型和测试用例的定义。 – Andre

+0

@Andre谢谢我添加了一个例子 –

+0

只是提示你的代码:而不是定义数据类型'StateSet'和'ActionSet',你可以使用Data.Set中的Set数据类型:https://hackage.haskell .org/package/containers-0.5.6.3/docs/Data-Set.html然后分别使用'Set State'和'Set Action',然后你可以使用一大堆有效的函数来处理集合,而不需要额外的努力 – hdgarrood

回答

1

我感觉和你刚开始学习函数式编程时一样 - 那calling functions on data types is nothing else than calling methods on immutable objects

我认为意识到这是看FP的一种方式,而不是唯一的方式是很重要的。同样,将数据和程序组合成类的OOP方法是考虑编程的一种方法,但不是唯一的方法。对于一些问题,面向对象的解决方案很好,而对于其他问题,则不太好。

你给的例子,或者您选择解决问题的方法,可能只是发生在一个更适合OOP比FP。并不是说你不能用FP解决它,只是这样做似乎有点尴尬和被迫 - 正如你注意到的那样。关于这个例子给你带来麻烦的原因,我的猜测是因为它涉及到改变一个环境 - 对OOP来说非常自然。

还有其他的问题,在该FP解决方案会显得自然而简单,OOP版本尴尬和强迫。考虑解决方案涉及将输入变换为输出的问题:

  • 输入:一组地图(即,一个数据库表)输出:一个报告,按照其中一列进行分组,在谓词上进行过滤,并将聚合函数应用于列
  • 输入:程序文本输出:分析树
  • 输入:分析树输出:函数长度,变量名称,注释数量等的统计信息。

总结一下,如果继续进行函数式编程,您会发现还有其他一些FP非常适合的问题,而且其解决方案比OO语言更简单自然。

+0

感谢您的快速回复。是的,我想我必须改变看待问题的方式。 –