簡體   English   中英

受歧視的工會的F#限制

[英]F# limitations of discriminated unions

我試圖將一個小編譯器從C#移植到F#,以利用模式匹配和區分聯合等功能。 目前,我使用基於System.Linq.Expressions的模式對AST進行建模:一個抽象基礎“Expression”類,每個表達式類型的派生類,以及允許在沒有大量轉換的情況下切換表達式的NodeType枚舉。 我曾希望使用F#區別聯盟大大減少這種情況,但我遇到了幾個看似有限的問題:

  • 強制公共默認構造函數(我想對表達式構造進行類型檢查和參數驗證,因為System.Linq.Expressions使用它的靜態工廠方法)
  • 缺少命名屬性(似乎這在F#3.1中已修復)
  • 無法直接引用案例類型。 例如,似乎我不能聲明一個只從聯合中獲取一個類型的函數(例如, let f (x : TYPE) = xExpression (聯合類型)編譯,但不為AddExpression.Add編譯。這似乎比我的C#方法犧牲了一些類型安全性。

對於這些或設計模式是否有良好的解決方法,使它們不那么令人沮喪?

我認為,對於DU是一個類層次結構的想法,你有點過分了。 將它真實地視為數據更有幫助。 因此:

  • 強制公共默認構造函數(我想對表達式構造進行類型檢查和參數驗證,因為System.Linq.Expressions使用它的靜態工廠方法)

DU只是數據,非常類似於字符串或數字,而不是功能。 為什么不創建一個函數來返回Expression option來表示您的數據可能無效。

  • 缺少命名屬性(似乎這在F#3.1中已修復)

如果您覺得需要命名屬性,則可能有一個不合適的類型,例如string * string * string * int * float作為Expression的數據。 更好地創建一個記錄,比如AddInfo並讓你使用DU的情況,比如說| Add of AddInfo | Add of AddInfo 這樣你就可以在模式匹配,智能感知等方面擁有屬性。

  • 無法直接引用案例類型。 例如,似乎我不能聲明一個只從聯合中獲取一個類型的函數(例如,讓f(x:TYPE)= x為表達式(聯合類型)編譯,但不為Add或Expression.Add編譯。這似乎比我的C#方法犧牲了一些類型安全性。

你不能要求一些東西成為Add case,但你絕對可以編寫一個帶有AddInfo的函數。 此外,您始終可以以monadic方式執行此操作,並且具有采用任何Expression功能,並且只返回option 在這種情況下,您可以模式匹配,您的輸入是適當的類型,如果不是,則返回None 在調用站點,您可以使用Option.bind函數在好的情況下“使用”該值。

基本上盡量不要將DU視為一組類,但實際上只是數據的情況。 有點像枚舉。

您可以將實現設為私有。 這使您可以在實現中充分發揮DU的功能,但對API的消費者提供有限的視圖。 有關記錄的相關問題,請參閱此答案 (盡管它也適用於DUs)。

編輯

我在MSDN上找不到語法,但這里是:

type T =
  private
  | A
  | B

private在這里意味着“私有模塊”。

暫無
暫無

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

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