Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 向函数传递数据类型与oop方法调用_Functional Programming - Fatal编程技术网

Functional programming 向函数传递数据类型与oop方法调用

Functional programming 向函数传递数据类型与oop方法调用,functional-programming,Functional Programming,从OOP开始,我在最近几周开始阅读函数式编程,并开始学习Haskell。我经常读到,(纯)函数更容易测试,因为没有复杂的设置和拆卸例程。这听起来很合理,我也同意。通过组合这些函数,我可以使用经过良好测试的“基”构建更复杂的函数 当我开始编写我的第一个程序时,一些函数得到了越来越多的参数,因此我开始创建新的数据类型,这些类型对我来说类似于结构。当然,数据类型将逻辑上属于一起的数据捆绑在一起,有时由其他数据类型组成 然后调用函数 MyTpye = foo(MyTpye, someParam) 感觉

从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)
type Action=[Double]
类型状态=[双精度]
数据状态集=状态集[状态]派生(显示)
数据ActionSet=ActionSet[Action]派生(显示)
数据环境=环境{
AvailableEstates::状态集,
availableActions::ActionSet,
当前状态::状态,
奖励FNC::状态->操作->双重,
最后奖励:双倍
} 
奖励函数::状态->操作->双重
报酬函数s a=(-1)
doAction::环境->操作->环境
doAction env a=环境(可用房地产环境)(可用反应环境)a(回报FNC环境)(回报FNC环境)(当前状态环境)a
获取奖励::环境->加倍
getReward环境=(lastReward环境)

states=StateSet[[i,j]| i我的感觉和我第一次开始学习函数式编程时的感觉一样,
对数据类型调用函数就是对不可变对象调用方法

我认为认识到这是看待FP的一种方法,而不是唯一的方法是很重要的。类似地,将数据和过程分组到类中的OOP方法是思考编程的一种方法,但不是唯一的方法。对于一些问题,OOP带来了很好的解决方案,而对于其他问题,它不是很好的解决方案

您给出的示例,或者您选择的解决方法,可能恰好更适合OOP而不是FP。并不是说您不能用FP解决它,只是这样做似乎有点尴尬和被迫——正如您所注意到的。我猜这个示例之所以给您带来麻烦,是因为它涉及到改变环境--对于OOP来说非常自然

对于其他问题,FP解决方案看起来自然而简单,OOP版本则笨拙而强制。想想解决方案涉及将输入转换为输出的问题:

  • 输入:一组映射(即一个数据库表)输出:一个报告,按一列分组,按谓词过滤,并对列应用聚合函数
  • 输入:程序文本输出:解析树
  • 输入:解析树输出:函数长度、变量名、注释数等的统计信息

总而言之,如果你继续使用函数式编程,你会发现FP非常适合解决其他问题,其解决方案比OO语言简单自然得多。

你能给出一个更具体的例子吗(最好是用Haskell,因为这是你要学的)?我看不出示例有任何错误(如果我将其理解为伪代码)。也许您可以提供类型定义和测试用例。@Andre谢谢,我为您的代码添加了一个示例只是一个提示:与其定义数据类型
StateSet
ActionSet
,不如在数据中使用Set数据类型。Set:然后分别使用
Set State
Set Action
,然后使用a使用一大堆有效的函数来处理集合而不需要任何额外的努力谢谢你的快速回复。是的,我想我必须改变我看待这个问题的方式。