来自OOP我在最近几周开始阅读有关函数式编程的知识,并开始学习Haskell。我经常读到(纯)函数更容易测试,因为没有复杂的设置和拆卸例程。这听起来很合理,我同意了。通过编写这些函数,我可以使用经过严格测试的“基础”构建更复杂的函数。
当我开始编写我的第一个程序时,一些函数获得了越来越多的参数,所以我开始创建新的数据类型,这对我来说类似于结构。当然,数据类型将逻辑上属于的内容捆绑在一起,有时由其他数据类型组成。
调用函数然后像
MyTpye = foo(MyTpye, someParam)
感觉有点像使用结构中的函数指针在C时代使用非常难看的语法来执行OOP:
MyType = foo(this, someParam) = {
...
return modified_copy_of_this;
}
测试这些功能还需要我首先设置我的新数据类型,这可能很复杂,我觉得我没有赢得多少。
我想我仍然过于狭隘,专注于OOP编写代码的方式。我只是觉得在数据类型上调用函数只不过是在不可变对象上调用方法(当然每个setter都必须返回对象的修改版本)。
有人可以帮我解释一下吗?
非常感谢!
我添加了这个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)
答案 0 :(得分:1)
我的感觉和我第一次开始学习函数式编程时的感觉一样 - calling functions on data types is nothing else than calling methods on immutable objects
。
我认为重要的是要意识到这是看待FP的一种方式,而不是唯一的方法。同时,将数据和过程分组到类中的OOP方法是思考编程的一种方式,但不是唯一的方法。对于某些问题,OOP可以提供很好的解决方案,而对于其他问题,它并不是那么好。
您给出的示例或您选择解决它的方式可能恰好适合OOP而不是FP。并不是说你不能用FP解决它,只是这样做似乎有点尴尬和强迫 - 正如你已经注意到的那样。我猜这个例子给你带来麻烦的原因是因为它涉及改变环境 - 对于OOP来说非常自然。
还有其他问题,FP解决方案看起来自然而简单,而且OOP版本笨拙且被迫。想想解决方案涉及将输入转换为输出的问题:
总而言之,如果你继续进行函数式编程,你会发现FP非常适合其他问题,并且其解决方案比在OO语言中更简单和自然。