2011-11-09 74 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

感謝您的快速回復。是的,我想我必須改變看待問題的方式。 –