簡體   English   中英

Haskell類型表示另一種類型的子集

[英]Haskell type representing a subset of another type

我認為當給定指定類型的參數時,函數永遠不會失敗。

但是看看這個看似無害的代碼:

readInts :: String -> [Int]
readInts = map read . words

它的類型簽名過於籠統,事實上,對於任何不是由空格分隔的整數組成的字符串,它都會失敗,其類型應為:

readInts :: SpaceSeparatedIntegersString -> [Int]

當您嘗試構建不遵守規定標准的SpaceSeparatedIntegersString時程序失敗。

  • 實現SpaceSeparatedIntegersString是一個明智的想法嗎?

  • 如果是我怎樣才能實現這樣的類型? (我只是問一個一般的想法/提示/推動正確的方向,而不是完整的代碼)

  • 我是否應該接受當String格式不正確時我的函數將失敗(也就是說,我在問題開頭的陳述是錯誤的)?

  • 我應該在函數定義中使用保護子句嗎?

你的目標是高尚的,但需要非常精確的類型。 依賴類型,例如Agda,Coq,Idris和其他語言中提供的類型可以實現您的建議。 例如在Coq,

Definition SpaceSeparatedIntegersString: Type :=
   { s: string | spaceSeparatedIntegers s } .
Definition spaceSeparatedIntegers (s: String): Prop := ...

問題在於,無論誰想要構造SpaceSeparatedIntegersString值,都必須提供相關屬性的正式證明。 這是可行的,但需要一些關心,時間和數學技能。

在Haskell中,將類型保證移動到輸出類型更為常見。 我們可以使輸出類型更弱,而不是使輸入類型更強:

readInts :: String -> Maybe [Int]

這不是那么精確,但可以在不必證明任何事情的情況下使用。

或者,通過在模塊中聲明它而不導出其值構造函數,使SpaceSeparatedIntegersString成為不透明類型。

module Foo(SpaceSeparatedIntegersString(), ...)
data SpaceSeparatedIntegersString = S String        -- S is private

這樣,模塊的用戶只能通過模塊導出的功能來操作它。 需要注意的是,可以制作一組(導出的)組合器,以保證SpaceSeparatedIntegersString類型的值永遠不會包含無效字符串。 例如,

combine :: SpaceSeparatedIntegersString 
        -> SpaceSeparatedIntegersString
        -> SpaceSeparatedIntegersString 
combine (S x) (S y) = S (x ++ " " ++ y)

這並不完全是直截了當的 - 如果你想允許一般的字符串操作,你可能會在某些情況下最終返回Maybe ...

您可能不應該實現SpaceSeparatedIntegerString 如果你做了抽象數據類型將是最簡單的事情。 你不應該接受你的功能應該失敗,至少不是在“模式匹配失敗”的意義上。 你應該創建一個返回Maybe [Int]類的函數。

你不應該實現SpaceSeparatedIntegerString的原因是可能只是將問題推到別處。 您可能從某些輸入獲取String ,所以在某處您需要一個函數String -> SpaceSeparatedIntegerString ,這也可能會失敗。 在某些時候,您需要從結構較少的數據轉換為更結構化的數據,除非您的唯一值是完全靜態指定的。

從結構較少的數據到更結構化的數據(或者更少類型的數據到更多類型的數據)的關鍵點實際上總是部分操作。 實際上,解析是將較少結構化數據轉換為更結構化數據的過程。 應該做的,不過,在與你的原則,就是盡可能的實際具體化回收的結構入式系統。 所以isValidUri :: String -> Bool是壞的,因為makeUri :: String -> Maybe String ,但是makeUri :: String -> Maybe Uri ,其中Uri是一個可以完全代表有效URI的類型。

不,在這種情況下,這不是一個明智的想法。 Ian Henry使用Maybe 的評論中提出的方法是幾個合理的方法之一。 其原因你的想法是在此上下文中明智的是,像一個函數的全部目的readInts是從用戶,文件,HTTP請求等,這可能是無效的處理的輸入。 如果您詢問用戶他們想購買多少輛汽車並且他們用小貓的照片回復,那么型號系統無法幫助您。 Derek Elkins真的更好地解釋了這一點。 一旦輸入完全驗證,chi的依賴類型方法對於其他一些情況非常有用。

暫無
暫無

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

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