design - Haskell的大規模設計?




functional-programming monads (6)

Don給了你上面大部分的細節,但是這是我在做Haskell的系統守護進程等真正有價值的有狀態程序時的兩分錢。

  1. 最後,你住在monad變壓器堆棧中。 最後是IO。 在此之上,每個主要模塊(抽象意義上而不是單元模塊意義上的)將其必要狀態映射到該堆棧中的一個層。 因此,如果你的數據庫連接代碼隱藏在一個模塊中,你可以把它全部寫入MonadReader Connection m => ... - > m ...中,然後你的數據庫函數總是可以在沒有其他函數的情況下獲得它們的連接模塊必須知道它的存在。 你最終可能會有一層承載你的數據庫連接,另外一個是你的配置,第三個是你的各種信號量和mvars,用於解決並行和同步問題,另一個是你的日誌文件處理等等。

  2. 首先找出你的錯誤處理。 Haskell在大型系統中最大的弱點是大量的錯誤處理方法,包括糟糕的錯誤處理方法(這是錯誤的,因為你無法返回任何錯誤信息;除非你真的使用Either而不是Maybe只是意味著缺失值)。 弄清楚你將如何首先完成它,並從你的庫和其他代碼使用的各種錯誤處理機制中設置適配器到最終的適配器中。 這會在以後拯救你一個悲傷的世界。

附錄 (摘自評論;感謝Lii & liminalisht ) -
更多討論關於將大型程序切割成單片機的不同方式:

Ben Kolera為這個主題提供了一個很好的實用介紹, Brian Hurt討論了解決Monadic行為問題的解決方案。 喬治威爾遜展示瞭如何使用mtl編寫與任何實現所需類型類的monad(而不是您自定義的monad類)兼容的代碼。 Carlo Hamalainen寫了一些總結喬治談話的簡短有用的筆記。

設計/構造大型函數程序的好方法是什麼,特別是在Haskell中?

我經歷了一系列的教程(寫自己的計劃是我最喜歡的,Real World Haskell緊隨其後) - 但大多數程序都相對較小,而且是單一用途。 此外,我不認為其中的一些特別優雅(例如,WYAS中的大量查找表)。

我現在想寫更大的程序,更多的移動部分 - 從各種不同的來源獲取數據,清理它,以各種方式處理它,在用戶界面中顯示它,堅持它,通過網絡進行通信等。一個最好的結構,這樣的代碼要清晰易讀,可維護,並且適應不斷變化的需求?

有相當多的文獻針對大型面向對象的命令式程序來解決這些問題。 像MVC,設計模式等理念是實現廣泛目標的體面處方,如OO風格的分離關注點和可重用性。 此外,較新的命令式語言適合於“設計成長”的重構風格,在我的新手觀點中,Haskell顯得不太合適。

Haskell有相當的文獻嗎? 功能性程序設計(單子,箭頭,應用等)中的外來控制結構的動物園如何最適用於此目的? 你可以推薦哪些最佳實踐?

謝謝!

編輯(這是唐斯圖爾特回答的後續):

@dons提到:“Monads可以捕獲類型中的關鍵架構設計。”

我想我的問題是:如何以純功能語言思考關鍵的架構設計?

考慮幾個數據流的例子,以及幾個處理步驟。 我可以將數據流的模塊化分析器編寫為一組數據結構,並且我可以將每個處理步驟作為純函數來實現。 一塊數據所需的處理步驟將取決於其值和其他值。 其中一些步驟應該跟隨GUI更新或數據庫查詢等副作用。

以合適的方式將數據和解析步驟聯繫起來的“正確”方法是什麼? 人們可以編寫一個大功能來為各種數據類型做正確的事情。 或者可以使用monad來跟踪到目前為止已處理的內容,並讓每個處理步驟從monad狀態下一步獲得所需內容。 或者可以編寫大量單獨的程序並發送消息(我不太喜歡這個選項)。

他鏈接的幻燈片有一個東西我們需要的項目符號:“用於將設計映射到類型/函數/類/ monads上的習語”。 成語是什麼? :)


本書第一次學習了結構化函數式編程。 它可能不是你正在尋找的東西,但對於函數式編程的初學者來說,這可能是學習構建函數式程序的最佳第一步 - 與規模無關。 在所有抽象層次上,設計應始終具有清晰的結構。

函數式編程的工藝

http://www.cs.kent.ac.uk/people/staff/sjt/craft2e/


加布里埃爾的博客文章可伸縮程序架構可能值得一提。

Haskell的設計模式與主流設計模式有一個重要的區別:

  • 常規體系結構 :將幾個組件組合在一起以生成類型B的“網絡”或“拓撲”

  • Haskell體系結構 :將A類型的幾個組件組合在一起以生成相同類型A的新組件,與其替代品無法區分

它經常讓我覺得,一個看似優雅的架構通常傾向於從表現出這種同質感的圖書館中以一種自下而上的方式脫落。 在Haskell中這尤其明顯 - 傳統上被認為是“自上而下”架構的模式往往會在mvcNetwireCloud Haskell等庫中被捕獲。 也就是說,我希望這個答案不會被解釋為替代這個線程中的其他任何人的嘗試,只是理論上的結構選擇可以並且應該由領域專家在圖書館中抽像出來。 在我看來,建立大型系統的真正困難在於評估這些圖書館的架構“優點”與所有務實的關注點。

正如liminalisht提到的那樣, 類別設計模式是Gabriel關於該主題的另一篇文章,也是類似的。


在Haskell中設計大型程序與在其他語言中進行設計沒有什麼不同。 大規模的編程就是將你的問題分解成易於管理的部分,以及如何將它們融合在一起; 實現語言不那麼重要。

這就是說,在一個大型設計中,嘗試和利用類型系統來確保你只能以正確的方式將你的作品拼湊在一起。 這可能涉及新類型或幻像類型,使看起來具有相同類型的東西不同。

在進行代碼重構時,純度是一個很大的好處,所以盡量保持純代碼盡可能多。 純代碼很容易重構,因為它與程序的其他部分沒有隱藏的交互。



我目前正在寫一本題為“Functional Design and Architecture”的書。 它為您提供了一套完整的技術,使用純功能方法構建一個大型應用程序。 它描述了許多功能模式和想法,同時構建了一個SCADA類應用程序'Andromeda',用於從頭開始控制飛船。 我的主要語言是Haskell。 本書涵蓋:

  • 使用圖表進行架構建模的方法;
  • 需求分析;
  • 嵌入式DSL域建模;
  • 外部DSL設計和實施;
  • Monad作為具有效果的子系統;
  • 免費monads作為功能接口;
  • 箭頭化的eDSL;
  • 使用免費的monadic eDSL進行控制反演;
  • 軟件事務內存;
  • 鏡頭;
  • 國家,讀者,作家,RWS,ST monads;
  • 不純狀態:IORef,MVar,STM;
  • 多線程和並行域建模;
  • GUI;
  • 主流技術和方法(如UML,SOLID,GRASP)的適用性;
  • 與不純的子系統交互。

您可能熟悉本書的代碼以及'Andromeda'項目代碼。

我希望在2017年底完成本書。在此之前,您可以在這裡閱讀我的文章“功能編程中的設計和架構”(Rus)。

UPDATE

我在網上分享了我的書(前5章)。 在Reddit上查看帖子







large-scale