我決定嘗試函數式編程和Purescript。在閱讀"Learn you a Haskell for great good"
和"PureScript by Example"
後,稍微玩了一段代碼,我認爲我可以說我明白了基本知識,但有一件事讓我很困擾 - 代碼看起來非常耦合。我通常經常更換庫,並且在OOP中,我可以使用洋蔥體系結構將我自己的代碼與庫特定的代碼解耦,但我不知道如何在Purescript中執行此操作。如何在purescript中構建應用程序
我試圖找到人們在Haskell中如何做到這一點,但我能找到的答案都是「沒有人在Haskell中製作過複雜的應用程序,所以沒有人知道如何做」或「你有輸入你有輸出,它們之間的一切都只是純粹的功能「。但在這一刻我有一個玩具應用程序,它使用虛擬儀器,信號,網絡存儲,路由器庫,並且它們每個都有自己的效果和數據結構,所以聽起來不像一個輸入和一個輸出。
所以我的問題是我應該如何構造我的代碼或我應該使用什麼工藝以便我可以更改我的庫而不必重寫我的一半應用程序?
更新:
建議使用幾層,並保持在主模塊中的效果是很常見也和我明白爲什麼我應該這樣做。
下面是一個簡單的例子,希望能說明我在談論的問題:
btnHandler :: forall ev eff. (MouseEvent ev) => ev -> Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace | eff) Unit
btnHandler e = do
btn <- getTarget e
Just btnId <- getAttribute "id" btn
Right clicks <- (getItem localStorage btnId) >>= readNumber
let newClicks = clicks + 1
trace $ "Button #" ++ btnId ++ " has been clicked " ++ (show newClicks) ++ " times"
setText (show newClicks) btn
setItem localStorage btnId $ show newClicks
-- ... maybe some other actions
return unit
-- ... other handlers for different controllers
btnController :: forall e. Node -> _ -> Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace | e) Unit
btnController mainEl _ = do
delegateEventListener mainEl "click" "#btn1" btnHandler
delegateEventListener mainEl "click" "#btn2" btnHandler
delegateEventListener mainEl "click" "#btn3" btnHandler
-- ... render buttons
return unit
-- ... other controllers
main :: forall e. Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace, router :: Router | e) Unit
main = do
Just mainEl <- body >>= querySelector "#wrapper"
handleRoute "/" $ btnController mainEl
-- ... other routes each with it's own controller
return unit
在這裏,我們有路由,網絡存儲,DOM操作和控制檯日誌記錄簡單的計數器的應用程序。正如你所看到的,沒有單一的輸入和單一的輸出。我們可以從路由器或事件監聽器獲得輸入,並使用console或dom作爲輸出,所以它變得稍微複雜一些。
擁有這一切effectful碼主模塊中的原因有兩個感覺不對我:
- 如果我將不斷增加航線和控制器該模塊將很快變成了一千行一塌糊塗。
- 飼養路由,DOM操作和數據在同一模塊中存儲違反了單一職責原則(我認爲這是很重要的FP太)
我們可以在這個模塊分割成幾個的,例如一個模塊每個控制器並創建一些有效的圖層。但是,當我有十個控制器模塊,並且我想更改我的dom特定庫時,我應該編輯它們。
這兩種方法都很不理想,所以問題是我應該選擇哪一個?或者也許還有其他方法可以去?
謝謝您的回答。我編輯了我的問題並添加了一個簡單的示例。 – starper