簡體   English   中英

使用Haskell的類型系統實現正確的抽象

[英]Achieving the right abstractions with Haskell's type system

我在優雅地使用Haskell的類型系統時遇到了麻煩。 我確定我的問題很常見,但除了特定於我的程序的術語外,我不知道如何描述它。

我試圖表達的概念是:

  • 數據點,每個數據點采用多種形式之一,例如(id,個案數,控件數),(id,個案數,人口數)

  • 數據點和集合信息的集合:(一組id,總案例,總控件),具有添加/刪除點的功能(因此對於每種不同的點,都有相應的各種集合)

我可以有一類點類型,並將各種點定義為自己的類型。 或者,我可以為每個品種提供一種點類型和不同的數據構造函數。 同樣對於點集。

我對每種方法都至少有一個問題:

  • 使用類型類:避免函數名稱沖突會很煩人。 例如,兩種類型的點都可以使用函數來提取“案例數”,但類型類不能要求此函數,因為某些其他點類型可能沒有案例。

  • 沒有類型類:我寧願不從Point模塊導出數據構造函數(提供其他更安全的函數來創建新值)。 如果沒有數據構造函數,我將無法確定給定Point值的變化。

什么樣的設計可以幫助減少這些(和其他)問題?

為了擴展sclv的答案,有一系列密切相關的概念,相當於提供一些解構價值的方法:Catamorphisms,它是廣義的折疊; 教會編碼,通過其操作來表示數據,並且通常等同於將解構主義部分地應用於它解構的值; CPS轉換,其中教會編碼類似於具體模式匹配,每個案例采用單獨的延續; 將數據表示為使用它的操作集合,通常稱為面向對象的編程; 等等。

在您的情況下,您似乎想要的是一個抽象類型 ,即不導出其內部表示的類型,但不是完全密封的類型,即使表示對定義它的模塊中的函數開放。 這與Data.Map.Map類的模式相同。 您可能希望使用類型類路由,因為它聽起來需要使用各種數據點,而不是單個類型的數據點的任意選擇。

最有可能的是,從模塊導出的“智能構造函數”的某種組合以及從模塊導出的各種解構函數(如上所述)是最佳起點。 從那里開始,我預計剩下的大部分細節應該有明顯的方法來接下來。

使用后一種解決方案(無類型類),您可以在類型而不是構造函數上導出catamorphism。

data MyData = PointData Double Double | ControlData Double Double Double | SomeOtherData String Double

foldMyData pf cf sf d = case d of
       (PointData x y) -> pf x y
       (ControlData x y z) -> cf x y z
       (SomeOtherData s x) -> sf s x

通過這種方式,您可以將數據分成任何您想要的內容(包括忽略值並傳遞返回您使用的構造函數的函數),而無需提供構建數據的一般方法。

只要您不打算在單個數據結構中混合使用不同的數據點,我就會發現基於類型的方法更好。

您提到的名稱沖突問題可以通過為每個不同的字段創建單獨的類型類來解決,如下所示:

class WithCases p where
    cases :: p -> NumberOfCases 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM